diff --git a/akka-modules/pom.xml b/akka-modules/pom.xml index 60432c4eea..be0b8aa891 100644 --- a/akka-modules/pom.xml +++ b/akka-modules/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 akka-modules - akka-modules pom + akka-modules parent-modules diff --git a/algorithms-modules/algorithms-miscellaneous-1/pom.xml b/algorithms-modules/algorithms-miscellaneous-1/pom.xml index a1ac607c29..b8c900ab98 100644 --- a/algorithms-modules/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-modules/algorithms-miscellaneous-1/pom.xml @@ -19,11 +19,6 @@ commons-math3 ${commons-math3.version} - - com.google.guava - guava - ${guava.version} - commons-codec commons-codec diff --git a/algorithms-modules/algorithms-miscellaneous-5/pom.xml b/algorithms-modules/algorithms-miscellaneous-5/pom.xml index 92b8e7d1f5..2d95bf2a01 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/pom.xml +++ b/algorithms-modules/algorithms-miscellaneous-5/pom.xml @@ -5,6 +5,18 @@ 4.0.0 algorithms-miscellaneous-5 0.0.1-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + algorithms-miscellaneous-5 @@ -29,11 +41,7 @@ tradukisto ${tradukisto.version} - - com.google.guava - guava - ${guava.version} - + jakarta.xml.bind diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java index ae434d88ad..5e4b35bfaf 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java @@ -1,15 +1,12 @@ package com.baeldung.algorithms.conversion; -import java.math.BigInteger; - - - +import com.google.common.io.BaseEncoding; +import jakarta.xml.bind.DatatypeConverter; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; -import com.google.common.io.BaseEncoding; - -import jakarta.xml.bind.DatatypeConverter; +import java.math.BigInteger; +import java.util.HexFormat; public class HexStringConverter { @@ -109,4 +106,14 @@ public class HexStringConverter { return BaseEncoding.base16() .decode(hexString.toUpperCase()); } + + public String encodeUsingHexFormat(byte[] bytes) { + HexFormat hexFormat = HexFormat.of(); + return hexFormat.formatHex(bytes); + } + + public byte[] decodeUsingHexFormat(String hexString) { + HexFormat hexFormat = HexFormat.of(); + return hexFormat.parseHex(hexString); + } } diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java b/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java index bb344e8b30..ee003ffac7 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java @@ -1,15 +1,13 @@ package com.baeldung.algorithms.conversion; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - import org.apache.commons.codec.DecoderException; import org.hamcrest.text.IsEqualIgnoringCase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.baeldung.algorithms.conversion.HexStringConverter; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class ByteArrayConverterUnitTest { @@ -24,7 +22,7 @@ class ByteArrayConverterUnitTest { void shouldEncodeByteArrayToHexStringUsingBigIntegerToString() { byte[] bytes = getSampleBytes(); String hexString = getSampleHexString(); - if(hexString.charAt(0) == '0') { + if (hexString.charAt(0) == '0') { hexString = hexString.substring(1); } String output = hexStringConverter.encodeUsingBigIntegerToString(bytes); @@ -46,7 +44,7 @@ class ByteArrayConverterUnitTest { byte[] output = hexStringConverter.decodeUsingBigInteger(hexString); assertArrayEquals(bytes, output); } - + @Test void shouldEncodeByteArrayToHexStringUsingCharacterConversion() { byte[] bytes = getSampleBytes(); @@ -62,7 +60,7 @@ class ByteArrayConverterUnitTest { byte[] output = hexStringConverter.decodeHexString(hexString); assertArrayEquals(bytes, output); } - + @Test void shouldDecodeHexToByteWithInvalidHexCharacter() { assertThrows(IllegalArgumentException.class, () -> { @@ -118,12 +116,28 @@ class ByteArrayConverterUnitTest { assertArrayEquals(bytes, output); } + @Test + void shouldEncodeByteArrayToHexStringUsingHexFormat() throws DecoderException { + byte[] bytes = getSampleBytes(); + String hexString = getSampleHexString(); + String output = hexStringConverter.encodeUsingHexFormat(bytes); + assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString)); + } + + @Test + void shouldDecodeHexStringToByteArrayUsingHexFormat() throws DecoderException { + byte[] bytes = getSampleBytes(); + String hexString = getSampleHexString(); + byte[] output = hexStringConverter.decodeUsingHexFormat(hexString); + assertArrayEquals(bytes, output); + } + private String getSampleHexString() { return "0af50c0e2d10"; } private byte[] getSampleBytes() { - return new byte[] { 10, -11, 12, 14, 45, 16 }; + return new byte[]{10, -11, 12, 14, 45, 16}; } } diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md index 881576f095..a08948eda5 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/README.md +++ b/algorithms-modules/algorithms-miscellaneous-7/README.md @@ -8,4 +8,10 @@ - [Find Missing Number From a Given Array in Java](https://www.baeldung.com/java-array-find-missing-number) - [Calculate Weighted Mean in Java](https://www.baeldung.com/java-compute-weighted-average) - [Check if Two Strings Are Rotations of Each Other](https://www.baeldung.com/java-string-check-strings-rotations) +- [Find the Largest Prime Under the Given Number in Java](https://www.baeldung.com/java-largest-prime-lower-threshold) +- [Count the Number of Unique Digits in an Integer using Java](https://www.baeldung.com/java-int-count-unique-digits) +- [Generate Juggler Sequence in Java](https://www.baeldung.com/java-generate-juggler-sequence) +- [Finding the Parent of a Node in a Binary Search Tree with Java](https://www.baeldung.com/java-find-parent-node-binary-search-tree) +- [Check if a Number Is a Happy Number in Java](https://www.baeldung.com/java-happy-sad-number-test) +- [Find the Largest Number Possible After Removing k Digits of a Number](https://www.baeldung.com/java-find-largest-number-remove-k-digits) - More articles: [[<-- prev]](/algorithms-miscellaneous-6) diff --git a/algorithms-modules/algorithms-miscellaneous-7/pom.xml b/algorithms-modules/algorithms-miscellaneous-7/pom.xml index 3703ea5a16..c520eb6c25 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/pom.xml +++ b/algorithms-modules/algorithms-miscellaneous-7/pom.xml @@ -13,4 +13,22 @@ 1.0.0-SNAPSHOT + + 1.35 + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigits.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigits.java new file mode 100644 index 0000000000..79086fc61f --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigits.java @@ -0,0 +1,57 @@ +package com.baeldung.algorithms.largestNumberRemovingK; + +import java.util.*; + +public class LargestNumberRemoveKDigits { + public static int findLargestNumberUsingArithmetic(int num, int k) { + for (int j = 0; j < k; j++) { + + int result = 0; + int i = 1; + + while (num / i > 0) { + int temp = (num / (i * 10)) + * i + + (num % i); + i *= 10; + + result = Math.max(result, temp); + } + num = result; + } + + return num; + } + + public static int findLargestNumberUsingStack(int num, int k) { + String numStr = Integer.toString(num); + int length = numStr.length(); + + if (k == length) return 0; + + Stack stack = new Stack<>(); + + for (int i = 0; i < length; i++) { + char digit = numStr.charAt(i); + + while (k > 0 && !stack.isEmpty() && stack.peek() < digit) { + stack.pop(); + k--; + } + + stack.push(digit); + } + + while (k > 0) { + stack.pop(); + k--; + } + + StringBuilder result = new StringBuilder(); + while (!stack.isEmpty()) { + result.insert(0, stack.pop()); + } + + return Integer.parseInt(result.toString()); + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumber.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumber.java new file mode 100644 index 0000000000..59b7e51a37 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumber.java @@ -0,0 +1,50 @@ +package com.baeldung.algorithms.perfectnumber; + +import java.util.stream.IntStream; + +class PerfectNumber { + + public static boolean isPerfectBruteForce(int number) { + int sum = 0; + for (int i = 1; i <= number / 2; i++) { + if (number % i == 0) { + sum += i; + } + } + return sum == number; + } + + public static boolean isPerfectStream(int number) { + int sum = IntStream.rangeClosed(2, (int) Math.sqrt(number)) + .filter(test -> number % test == 0) + .reduce(1, (s, test) -> s + test + (number / test)); + return sum == number; + } + + public static boolean isPerfectEuclidEuler(int number) { + int p = 2; + int perfectNumber = (int) (Math.pow(2, p - 1) * (Math.pow(2, p) - 1)); + while (perfectNumber <= number) { + if (perfectNumber == number) { + return true; + } + p++; + perfectNumber = (int) (Math.pow(2, p - 1) * (Math.pow(2, p) - 1)); + } + return false; + } + + public static boolean isPerfectEuclidEulerUsingShift(int number) { + int p = 2; + int perfectNumber = (2 << (p - 1)) * ((2 << p) - 1); + while (perfectNumber <= number) { + if (perfectNumber == number) { + return true; + } + p++; + perfectNumber = (2 << (p - 1)) * ((2 << p) - 1); + } + return false; + } + +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumberBenchmark.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumberBenchmark.java new file mode 100644 index 0000000000..9890c2887f --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/perfectnumber/PerfectNumberBenchmark.java @@ -0,0 +1,41 @@ +package com.baeldung.algorithms.perfectnumber; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@State(Scope.Benchmark) +public class PerfectNumberBenchmark { + + @Benchmark + public boolean bruteForceBenchmark() { + return PerfectNumber.isPerfectBruteForce(33550336); + } + + @Benchmark + public boolean streamBenchmark() { + return PerfectNumber.isPerfectStream(33550336); + } + + @Benchmark + public boolean euclidEulerBenchmark() { + return PerfectNumber.isPerfectEuclidEuler(33550336); + } + + @Benchmark + public boolean euclidEulerUsingShiftBenchmark() { + return PerfectNumber.isPerfectEuclidEulerUsingShift(33550336); + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(PerfectNumberBenchmark.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(options).run(); + } +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg b/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg index c2f035ae64..5efe04c33a 100644 Binary files a/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg and b/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg differ diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java new file mode 100644 index 0000000000..2056688659 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java @@ -0,0 +1,82 @@ +package com.baeldung.algorithms.happynumber; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +class HappyNumberDecider { + + public static boolean isHappyNumber(int n) { + Set checkedNumbers = new HashSet<>(); + while (true) { + n = sumDigitsSquare(n); + if (n == 1) { + return true; + } + if (checkedNumbers.contains(n)) { + return false; + } + checkedNumbers.add(n); + } + } + + public static boolean isHappyNumberFloyd(int n) { + int slow = n; + int fast = n; + do { + slow = sumDigitsSquare(slow); + fast = sumDigitsSquare(sumDigitsSquare(fast)); + } while (slow != fast); + + return slow == 1; + } + + private static int sumDigitsSquare(int n) { + int squareSum = 0; + while (n != 0) { + squareSum += (n % 10) * (n % 10); + n /= 10; + } + return squareSum; + } +} + +public class HappyNumberUnitTest { + + @Test + void whenUsingIsHappyNumber_thenGetTheExpectedResult() { + assertTrue(HappyNumberDecider.isHappyNumber(7)); + assertTrue(HappyNumberDecider.isHappyNumber(10)); + assertTrue(HappyNumberDecider.isHappyNumber(13)); + assertTrue(HappyNumberDecider.isHappyNumber(19)); + assertTrue(HappyNumberDecider.isHappyNumber(23)); + + assertFalse(HappyNumberDecider.isHappyNumber(4)); + assertFalse(HappyNumberDecider.isHappyNumber(6)); + assertFalse(HappyNumberDecider.isHappyNumber(11)); + assertFalse(HappyNumberDecider.isHappyNumber(15)); + assertFalse(HappyNumberDecider.isHappyNumber(20)); + + } + + @Test + void whenUsingIsHappyNumber2_thenGetTheExpectedResult() { + assertTrue(HappyNumberDecider.isHappyNumberFloyd(7)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(10)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(13)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(19)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(23)); + + assertFalse(HappyNumberDecider.isHappyNumberFloyd(4)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(6)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(11)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(15)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(20)); + + } + +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigitsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigitsUnitTest.java new file mode 100644 index 0000000000..5325a27609 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/largestNumberRemovingK/LargestNumberRemoveKDigitsUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.algorithms.largestNumberRemovingK; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class LargestNumberRemoveKDigitsUnitTest { + + @Test + public void givenNumber_UsingArithmeticRemoveKDigits_thenReturnLargestNumber(){ + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingArithmetic(9461, 1), 961); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingArithmetic(463, 2), 6); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingArithmetic(98625410, 6), 98); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingArithmetic(20, 2), 0); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingArithmetic(98989, 4), 9); + } + + @Test + public void givenNumber_UsingStackRemoveKDigits_thenReturnLargestNumber(){ + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingStack(9461, 1), 961); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingStack(463, 2), 6); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingStack(98625410, 6), 98); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingStack(20, 2), 0); + Assertions.assertEquals(LargestNumberRemoveKDigits.findLargestNumberUsingStack(98989, 4), 9); + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/perfectnumber/PerfectNumberUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/perfectnumber/PerfectNumberUnitTest.java new file mode 100644 index 0000000000..e03e7c8653 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/perfectnumber/PerfectNumberUnitTest.java @@ -0,0 +1,68 @@ +package com.baeldung.algorithms.perfectnumber; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PerfectNumberUnitTest { + @Test + void givenPerfectNumber_whenCheckingIsPerfectBruteForce_thenReturnTrue() { + assertTrue(PerfectNumber.isPerfectBruteForce(6)); + } + + @Test + void givenNonPerfectNumber_whenCheckingIsPerfectBruteForce_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectBruteForce(10)); + } + + @Test + void givenNegativeNumber_whenCheckingIsPerfectBruteForce_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectBruteForce(-28)); + } + + @Test + void givenPerfectNumber_whenCheckingIsPerfectStream_thenReturnTrue() { + assertTrue(PerfectNumber.isPerfectStream(28)); + } + + @Test + void givenNonPerfectNumber_whenCheckingIsPerfectStream_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectStream(10)); + } + + @Test + void givenNegativeNumber_whenCheckingIsPerfectStream_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectStream(-6)); + } + + @Test + void givenPerfectNumber_whenCheckingIsPerfectEuclidEuler_thenReturnTrue() { + assertTrue(PerfectNumber.isPerfectEuclidEuler(28)); + } + + @Test + void givenNonPerfectNumber_whenCheckingIsPerfectEuclidEuler_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectEuclidEuler(10)); + } + + @Test + void givenNegativeNumber_whenCheckingIsPerfectEuclidEuler_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectEuclidEuler(-6)); + } + + @Test + void givenPerfectNumber_whenCheckingIsPerfectEuclidEulerUsingShift_thenReturnTrue() { + assertTrue(PerfectNumber.isPerfectEuclidEulerUsingShift(28)); + } + + @Test + void givenNonPerfectNumber_whenCheckingIsPerfectEuclidEulerUsingShift_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectEuclidEulerUsingShift(10)); + } + + @Test + void givenNegativeNumber_whenCheckingIsPerfectEuclidEulerUsingShift_thenReturnFalse() { + assertFalse(PerfectNumber.isPerfectEuclidEulerUsingShift(-6)); + } +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-8/README.md b/algorithms-modules/algorithms-miscellaneous-8/README.md new file mode 100644 index 0000000000..e2c5047136 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: +- [Vigenère Cipher in Java](https://www.baeldung.com/java-vigenere-cipher) +- [Merge Overlapping Intervals in a Java Collection](https://www.baeldung.com/java-collection-merge-overlapping-intervals) diff --git a/docker-modules/docker-caching/pom.xml b/algorithms-modules/algorithms-miscellaneous-8/pom.xml similarity index 58% rename from docker-modules/docker-caching/pom.xml rename to algorithms-modules/algorithms-miscellaneous-8/pom.xml index 25572dfe4f..29163c5de7 100644 --- a/docker-modules/docker-caching/pom.xml +++ b/algorithms-modules/algorithms-miscellaneous-8/pom.xml @@ -3,19 +3,14 @@ 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 - docker-caching - docker-caching - pom + algorithms-miscellaneous-8 + 0.0.1-SNAPSHOT + algorithms-miscellaneous-8 - docker-modules com.baeldung + algorithms-modules 1.0.0-SNAPSHOT - - single-module-caching - multi-module-caching - - - \ No newline at end of file + diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java new file mode 100644 index 0000000000..f926d578be --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java @@ -0,0 +1,37 @@ +package com.baeldung.algorithms.mergeintervals; + +import java.util.Objects; + +public class Interval { + int start; + int end; + + Interval(int start, int end) { + this.start = start; + this.end = end; + } + + public void setEnd(int end) { + this.end = end; + } + + @Override + public String toString() { + return "Interval{" + "start=" + start + ", end=" + end + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Interval interval = (Interval) o; + return start == interval.start && end == interval.end; + } + + @Override + public int hashCode() { + return Objects.hash(start, end); + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java new file mode 100644 index 0000000000..ba424772d5 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.mergeintervals; + +import java.util.ArrayList; +import java.util.List; + +public class MergeOverlappingIntervals { + + public List doMerge(List intervals) { + // Sort the intervals based on start time + intervals.sort((one, two) -> one.start - two.start); + + // Create somewhere to put the merged list, start it off with the earliest starting interval + ArrayList merged = new ArrayList<>(); + merged.add(intervals.get(0)); + + // Loop over each interval and merge if start time is before the end time of the + // previous interval + intervals.forEach(interval -> { + if (merged.get(merged.size() - 1).end > interval.start) { + merged.get(merged.size() - 1).setEnd(interval.end); + } else { + merged.add(interval); + } + }); + + return merged; + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java new file mode 100644 index 0000000000..52192415df --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java @@ -0,0 +1,11 @@ +package com.baeldung.algorithms.skiplist; + +class Node { + int value; + Node[] forward; // array to hold references to different levels + + public Node(int value, int level) { + this.value = value; + this.forward = new Node[level + 1]; // level + 1 because level is 0-based + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java new file mode 100644 index 0000000000..53f7a3b0c8 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java @@ -0,0 +1,92 @@ +package com.baeldung.algorithms.skiplist; + + +import java.util.Random; + +public class SkipList { + private Node head; + private int maxLevel; + private int level; + private Random random; + + public SkipList() { + maxLevel = 16; // maximum number of levels + level = 0; // current level of SkipList + head = new Node(Integer.MIN_VALUE, maxLevel); + random = new Random(); + } + + public void insert(int value) { + Node[] update = new Node[maxLevel + 1]; + Node current = this.head; + + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + update[i] = current; + } + + current = current.forward[0]; + + if (current == null || current.value != value) { + int lvl = randomLevel(); + + if (lvl > level) { + for (int i = level + 1; i <= lvl; i++) { + update[i] = head; + } + level = lvl; + } + + Node newNode = new Node(value, lvl); + for (int i = 0; i <= lvl; i++) { + newNode.forward[i] = update[i].forward[i]; + update[i].forward[i] = newNode; + } + } + } + + public boolean search(int value) { + Node current = this.head; + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + } + current = current.forward[0]; + return current != null && current.value == value; + } + + public void delete(int value) { + Node[] update = new Node[maxLevel + 1]; + Node current = this.head; + + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + update[i] = current; + } + current = current.forward[0]; + + if (current != null && current.value == value) { + for (int i = 0; i <= level; i++) { + if (update[i].forward[i] != current) break; + update[i].forward[i] = current.forward[i]; + } + + while (level > 0 && head.forward[level] == null) { + level--; + } + } + } + + private int randomLevel() { + int lvl = 0; + while (lvl < maxLevel && random.nextDouble() < 0.5) { + lvl++; + } + return lvl; + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java new file mode 100644 index 0000000000..5f15fe00f6 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.algorithms.mergeintervals; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +class MergeIntervalsUnitTest { + + private ArrayList intervals = new ArrayList<>(Arrays.asList( + new Interval(2, 5), + new Interval(13, 20), + new Interval(11, 15), + new Interval(1, 3) + )); + private ArrayList intervalsMerged = new ArrayList<>(Arrays.asList( + new Interval(1, 5), + new Interval(11, 20) + )); + + @Test + void givenIntervals_whenMerging_thenReturnMergedIntervals() { + MergeOverlappingIntervals merger = new MergeOverlappingIntervals(); + ArrayList result = (ArrayList) merger.doMerge(intervals); + assertArrayEquals(intervalsMerged.toArray(), result.toArray()); + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java new file mode 100644 index 0000000000..6f8e5d042c --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.algorithms.skiplist; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SkipListUnitTest { + + @Test + public void givenSkipList_WhenInsert_ThenSearchFound() { + SkipList skipList = new SkipList(); + + skipList.insert(3); + assertTrue(skipList.search(3), "Should find 3"); + + assertFalse(skipList.search(99), "Should not find 99"); + } + + @Test + public void givenSkipList_WhenDeleteElement_ThenRemoveFromList() { + SkipList skipList = new SkipList(); + + skipList.insert(3); + skipList.insert(7); + + skipList.delete(3); + assertFalse(skipList.search(3), "3 should have been deleted"); + + skipList.delete(99); + assertTrue(skipList.search(7), "7 should still exist"); + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipher.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipher.java new file mode 100644 index 0000000000..37a7c13d17 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipher.java @@ -0,0 +1,69 @@ +package com.baeldung.algorithms.vigenere; + +public class VigenereCipher { + private final String characters; + + public VigenereCipher() { + this("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + } + + public VigenereCipher(String characters) { + this.characters = characters; + } + + public String encode(String input, String key) { + String result = ""; + + int keyPosition = 0; + for (char c : input.toCharArray()) { + char k = key.charAt(keyPosition % key.length()); + + int charIndex = characters.indexOf(c); + int keyIndex = characters.indexOf(k); + + if (charIndex >= 0) { + if (keyIndex >= 0) { + int newCharIndex = (charIndex + keyIndex + 1) % characters.length(); + c = characters.charAt(newCharIndex); + + } + + keyPosition++; + } + + result += c; + } + + return result; + } + + public String decode(String input, String key) { + String result = ""; + + int keyPosition = 0; + for (char c : input.toCharArray()) { + char k = key.charAt(keyPosition % key.length()); + + int charIndex = characters.indexOf(c); + int keyIndex = characters.indexOf(k); + + if (charIndex >= 0) { + if (keyIndex >= 0) { + int newCharIndex = charIndex - keyIndex - 1; + if (newCharIndex < 0) { + newCharIndex = characters.length() + newCharIndex; + } + c = characters.charAt(newCharIndex); + + } + + keyPosition++; + } + + result += c; + } + + return result; + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipherUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipherUnitTest.java new file mode 100644 index 0000000000..ea463caa08 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/vigenere/VigenereCipherUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.algorithms.vigenere; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class VigenereCipherUnitTest { + + @Test + void encodeBaeldung() { + VigenereCipher cipher = new VigenereCipher(); + String output = cipher.encode("BAELDUNG", "HELLO"); + + Assertions.assertEquals("JFQXSCSS", output); + } + + @Test + void encodeBaeldungMixedCharacters() { + VigenereCipher cipher = new VigenereCipher("JQFVHPWORZSLNMKYCGBUXIEDTA"); + String output = cipher.encode("BAELDUNG", "HELLO"); + + Assertions.assertEquals("DERDPTZV", output); + } + + @Test + void encodeArticleTitle() { + VigenereCipher cipher = new VigenereCipher(); + String output = cipher.encode("VIGENERE CIPHER IN JAVA", "BAELDUNG"); + + Assertions.assertEquals("XJLQRZFL EJUTIM WU LBAM", output); + } + + @Test + void encodeArticleTitleMoreCharacters() { + VigenereCipher cipher = new VigenereCipher("ABCDEFGHIJKLMNOPQRSTUVWXYZ "); + String output = cipher.encode("VIGENERE CIPHER IN JAVA", "BAELDUNG"); + + Assertions.assertEquals("XJLQRZELBDNALZEGKOEVEPO", output); + } + + @Test + void decodeBaeldung() { + VigenereCipher cipher = new VigenereCipher(); + String output = cipher.decode("JFQXSCSS", "HELLO"); + + Assertions.assertEquals("BAELDUNG", output); + } + + @Test + void decodeBaeldungMixedCharacters() { + VigenereCipher cipher = new VigenereCipher("JQFVHPWORZSLNMKYCGBUXIEDTA"); + String output = cipher.decode("DERDPTZV", "HELLO"); + + Assertions.assertEquals("BAELDUNG", output); + } + + @Test + void decodeArticleTitleMoreCharacters() { + VigenereCipher cipher = new VigenereCipher("ABCDEFGHIJKLMNOPQRSTUVWXYZ "); + String output = cipher.decode("XJLQRZELBDNALZEGKOEVEPO", "BAELDUNG"); + + Assertions.assertEquals("VIGENERE CIPHER IN JAVA", output); + } + + @Test + void encodeDecodeBaeldung() { + VigenereCipher cipher = new VigenereCipher(); + + String input = "BAELDUNG"; + String key = "HELLO"; + + String encoded = cipher.encode(input, key); + String decoded = cipher.decode(encoded, key); + + Assertions.assertEquals(input, decoded); + } +} diff --git a/algorithms-modules/pom.xml b/algorithms-modules/pom.xml index fda8eea0e7..d3f27f4fa8 100644 --- a/algorithms-modules/pom.xml +++ b/algorithms-modules/pom.xml @@ -22,6 +22,7 @@ algorithms-miscellaneous-5 algorithms-miscellaneous-6 algorithms-miscellaneous-7 + algorithms-miscellaneous-8 algorithms-searching algorithms-sorting algorithms-sorting-2 @@ -34,4 +35,4 @@ 1.0.1 - \ No newline at end of file + diff --git a/apache-cxf-modules/cxf-spring/pom.xml b/apache-cxf-modules/cxf-spring/pom.xml index 234a19eebc..e1e5033e2d 100644 --- a/apache-cxf-modules/cxf-spring/pom.xml +++ b/apache-cxf-modules/cxf-spring/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 cxf-spring - cxf-spring war + cxf-spring com.baeldung diff --git a/apache-cxf-modules/pom.xml b/apache-cxf-modules/pom.xml index 245a31614b..a571f5477c 100644 --- a/apache-cxf-modules/pom.xml +++ b/apache-cxf-modules/pom.xml @@ -5,8 +5,9 @@ 4.0.0 apache-cxf-modules 0.0.1-SNAPSHOT - apache-cxf-modules pom + apache-cxf-modules + com.baeldung diff --git a/apache-cxf-modules/sse-jaxrs/pom.xml b/apache-cxf-modules/sse-jaxrs/pom.xml index baa32a516a..2fade99152 100644 --- a/apache-cxf-modules/sse-jaxrs/pom.xml +++ b/apache-cxf-modules/sse-jaxrs/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 sse-jaxrs - sse-jaxrs pom + sse-jaxrs com.baeldung diff --git a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/pom.xml b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/pom.xml index 3bd3e5cb27..13ec2a681f 100644 --- a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/pom.xml +++ b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 sse-jaxrs-server - sse-jaxrs-server war + sse-jaxrs-server com.baeldung diff --git a/apache-httpclient4/pom.xml b/apache-httpclient4/pom.xml index 90890ef7b9..89e85fc1b4 100644 --- a/apache-httpclient4/pom.xml +++ b/apache-httpclient4/pom.xml @@ -5,8 +5,8 @@ 4.0.0 apache-httpclient4 0.1-SNAPSHOT - apache-httpclient4 war + apache-httpclient4 com.baeldung @@ -82,7 +82,7 @@ org.springframework spring-oxm - ${spring.version} + ${spring-oxm.version} @@ -176,12 +176,6 @@ ${jstl.version} runtime - - - com.google.guava - guava - ${guava.version} - org.springframework @@ -199,7 +193,6 @@ true - @@ -233,6 +226,7 @@ + 6.1.4 1.16.0 4.1.5 diff --git a/apache-kafka-2/README.md b/apache-kafka-2/README.md index bc3a8885bf..c938e70f6b 100644 --- a/apache-kafka-2/README.md +++ b/apache-kafka-2/README.md @@ -16,3 +16,4 @@ You can build the project from the command line using: *mvn clean install*, or i - [Introduction to Apache Kafka](https://www.baeldung.com/apache-kafka) - [Ensuring Message Ordering in Kafka: Strategies and Configurations](https://www.baeldung.com/kafka-message-ordering) - [Read Multiple Messages with Apache Kafka](https://www.baeldung.com/kafka-read-multiple-messages) +- [Creating a Kafka Listener Using the Consumer API](https://www.baeldung.com/kafka-create-listener-consumer-api) diff --git a/apache-kafka-3/README.md b/apache-kafka-3/README.md new file mode 100644 index 0000000000..a2a99425f9 --- /dev/null +++ b/apache-kafka-3/README.md @@ -0,0 +1,10 @@ +## Apache Kafka + +This module contains articles about Apache Kafka. + +##### Building the project +You can build the project from the command line using: *mvn clean install*, or in an IDE. + +### Relevant Articles: +- [Commit Offsets in Kafka](https://www.baeldung.com/kafka-commit-offsets) + diff --git a/apache-kafka-3/pom.xml b/apache-kafka-3/pom.xml new file mode 100644 index 0000000000..ad51e1de44 --- /dev/null +++ b/apache-kafka-3/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + apache-kafka-3 + apache-kafka-3 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.apache.kafka + kafka-clients + ${kafka.version} + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.databind.version} + + + + + 3.6.1 + 2.15.2 + + + + integration-jdk9-and-above + + + \ No newline at end of file diff --git a/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AsyncCommit.java b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AsyncCommit.java new file mode 100644 index 0000000000..6b6e615d65 --- /dev/null +++ b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AsyncCommit.java @@ -0,0 +1,23 @@ +package com.baeldung.kafka.commitoffset; + +import com.baeldung.kafka.commitoffset.config.KafkaConfigProperties; + +import java.time.Duration; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; + +public class AsyncCommit { + + public static void main(String[] args) { + + KafkaConsumer consumer = new KafkaConsumer<>(KafkaConfigProperties.getProperties()); + consumer.subscribe(KafkaConfigProperties.getTopic()); + ConsumerRecords messages = consumer.poll(Duration.ofSeconds(10)); + for (ConsumerRecord message : messages) { + // processed message + consumer.commitAsync(); + } + } +} diff --git a/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AutomaticCommit.java b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AutomaticCommit.java new file mode 100644 index 0000000000..6fca7db43a --- /dev/null +++ b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/AutomaticCommit.java @@ -0,0 +1,26 @@ +package com.baeldung.kafka.commitoffset; + +import com.baeldung.kafka.commitoffset.config.KafkaConfigProperties; + +import java.time.Duration; +import java.util.Properties; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; + +public class AutomaticCommit { + + public static void main(String[] args) { + + Properties properties = KafkaConfigProperties.getProperties(); + properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true"); + KafkaConsumer consumer = new KafkaConsumer<>(properties); + consumer.subscribe(KafkaConfigProperties.getTopic()); + ConsumerRecords messages = consumer.poll(Duration.ofSeconds(10)); + for (ConsumerRecord message : messages) { + // processed message + } + } +} diff --git a/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SpecificOffsetCommit.java b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SpecificOffsetCommit.java new file mode 100644 index 0000000000..07f099a844 --- /dev/null +++ b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SpecificOffsetCommit.java @@ -0,0 +1,34 @@ +package com.baeldung.kafka.commitoffset; + +import com.baeldung.kafka.commitoffset.config.KafkaConfigProperties; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.common.TopicPartition; + +public class SpecificOffsetCommit { + public static void main(String[] args) { + + KafkaConsumer consumer = new KafkaConsumer<>(KafkaConfigProperties.getProperties()); + consumer.subscribe(KafkaConfigProperties.getTopic()); + Map currentOffsets = new HashMap<>(); + int messageProcessed = 0; + while (true) { + ConsumerRecords messages = consumer.poll(Duration.ofSeconds(10)); + for (ConsumerRecord message : messages) { + // processed message + messageProcessed++; + currentOffsets.put(new TopicPartition(message.topic(), message.partition()), new OffsetAndMetadata(message.offset() + 1)); + if (messageProcessed % 50 == 0) { + consumer.commitSync(currentOffsets); + } + } + } + } +} diff --git a/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SyncCommit.java b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SyncCommit.java new file mode 100644 index 0000000000..54f6b5f826 --- /dev/null +++ b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/SyncCommit.java @@ -0,0 +1,23 @@ +package com.baeldung.kafka.commitoffset; + +import com.baeldung.kafka.commitoffset.config.KafkaConfigProperties; + +import java.time.Duration; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; + +public class SyncCommit { + + public static void main(String[] args) { + + KafkaConsumer consumer = new KafkaConsumer<>(KafkaConfigProperties.getProperties()); + consumer.subscribe(KafkaConfigProperties.getTopic()); + ConsumerRecords messages = consumer.poll(Duration.ofSeconds(10)); + for (ConsumerRecord message : messages) { + // processed message + consumer.commitSync(); + } + } +} diff --git a/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/config/KafkaConfigProperties.java b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/config/KafkaConfigProperties.java new file mode 100644 index 0000000000..9b2096a610 --- /dev/null +++ b/apache-kafka-3/src/main/java/com/baeldung/kafka/commitoffset/config/KafkaConfigProperties.java @@ -0,0 +1,31 @@ +package com.baeldung.kafka.commitoffset.config; + +import java.util.ArrayList; +import java.util.Properties; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; + +/** + * @author amitkumar + */ +public class KafkaConfigProperties { + public static final String MY_TOPIC = "my-topic"; + + public static Properties getProperties() { + + Properties props = new Properties(); + props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "MyFirstConsumer"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + return props; + } + + public static ArrayList getTopic() { + ArrayList topics = new ArrayList<>(); + topics.add(MY_TOPIC); + return topics; + } +} diff --git a/apache-kafka-3/src/test/resources/logback.xml b/apache-kafka-3/src/test/resources/logback.xml new file mode 100644 index 0000000000..6156c2188e --- /dev/null +++ b/apache-kafka-3/src/test/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/apache-kafka/pom.xml b/apache-kafka/pom.xml index 6aa5fb894a..8bdcd30ebd 100644 --- a/apache-kafka/pom.xml +++ b/apache-kafka/pom.xml @@ -71,11 +71,6 @@ ${flink.version} test - - com.google.guava - guava - ${guava.version} - org.awaitility awaitility diff --git a/apache-libraries-2/README.md b/apache-libraries-2/README.md index c80677a4bc..f7cdae70d7 100644 --- a/apache-libraries-2/README.md +++ b/apache-libraries-2/README.md @@ -1,3 +1,6 @@ ## Relevant Articles - [Understanding XSLT Processing in Java](https://www.baeldung.com/java-extensible-stylesheet-language-transformations) - [Add Camel Route at Runtime in Java](https://www.baeldung.com/java-camel-dynamic-route) +- [Logging in Apache Camel](https://www.baeldung.com/java-apache-camel-logging) +- More articles: [[<-- prev]](../apache-libraries) + diff --git a/apache-libraries-2/data/inbox/welcome.txt b/apache-libraries-2/data/inbox/welcome.txt new file mode 100644 index 0000000000..9f55d12685 --- /dev/null +++ b/apache-libraries-2/data/inbox/welcome.txt @@ -0,0 +1 @@ +Welcome to Baeldung \ No newline at end of file diff --git a/apache-libraries-2/data/json/name.json b/apache-libraries-2/data/json/name.json new file mode 100644 index 0000000000..1f7e064a56 --- /dev/null +++ b/apache-libraries-2/data/json/name.json @@ -0,0 +1,4 @@ +{ + "name" : "phillip", + "age" : 5 +} \ No newline at end of file diff --git a/apache-libraries-2/data/outbox/welcome.txt b/apache-libraries-2/data/outbox/welcome.txt new file mode 100644 index 0000000000..c4c82085cb --- /dev/null +++ b/apache-libraries-2/data/outbox/welcome.txt @@ -0,0 +1 @@ +WELCOME TO BAELDUNG \ No newline at end of file diff --git a/apache-libraries-2/data/output/name.json b/apache-libraries-2/data/output/name.json new file mode 100644 index 0000000000..d075754d1b --- /dev/null +++ b/apache-libraries-2/data/output/name.json @@ -0,0 +1 @@ +{"name":"phillip","age":5,"transformedName":"PHILLIP","transformedAge":15} \ No newline at end of file diff --git a/apache-libraries-2/pom.xml b/apache-libraries-2/pom.xml index 2e7ef0344c..b1e1a47d5f 100644 --- a/apache-libraries-2/pom.xml +++ b/apache-libraries-2/pom.xml @@ -24,24 +24,27 @@ camel-core ${camel.version} - org.apache.camel camel-test-junit5 ${camel.version} test - org.apache.camel camel-main ${camel.version} + + org.apache.camel + camel-jackson + ${camel.version} + 2.0.1.Final - 4.3.0 + 4.4.1 \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java new file mode 100644 index 0000000000..8eaad95959 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java @@ -0,0 +1,13 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.main.Main; + +public class CamelLoggingMainApp { + + public static void main(String[] args) throws Exception { + Main main = new Main(); + main.configure() + .addRoutesBuilder(new FileCopierCamelRoute()); + main.run(args); + } +} diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java new file mode 100644 index 0000000000..cd09174d54 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java @@ -0,0 +1,25 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.LoggingLevel; +import org.apache.camel.builder.RouteBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileCopierCamelRoute extends RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(FileCopierCamelRoute.class); + + public void configure() { + from("file:data/inbox?noop=true").log("We got an incoming file ${file:name} containing: ${body}") + .to("log:com.baeldung.apachecamellogging?level=INFO") + .process(process -> { + LOGGER.info("We are passing the message to a FileProcesor bean to capitalize the message body"); + }) + .bean(FileProcessor.class) + .to("file:data/outbox") + .to("log:com.baeldung.apachecamellogging?showBodyType=false&maxChars=20") + .log(LoggingLevel.DEBUG, "Output Process", "The Process ${id}") + .log("Successfully transfer file: ${file:name}"); + } +} \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java new file mode 100644 index 0000000000..fea144ce66 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java @@ -0,0 +1,22 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.dataformat.JsonLibrary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileCopierTracerCamelRoute extends RouteBuilder { + + Logger logger = LoggerFactory.getLogger(FileCopierTracerCamelRoute.class); + + public void configure() { + getContext().setTracing(true); + from("file:data/json?noop=true").to("log:input?level=INFO") + .unmarshal() + .json(JsonLibrary.Jackson) + .bean(FileProcessor.class, "transform") + .marshal() + .json(JsonLibrary.Jackson) + .to("file:data/output"); + } +} \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java new file mode 100644 index 0000000000..478fb0ced0 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java @@ -0,0 +1,23 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.Body; + +import java.util.Map; + +public class FileProcessor { + + public String process(@Body String fileContent) { + String processedContent = fileContent.toUpperCase(); + return processedContent; + } + + public Map transform(Map input) { + String name = (String) input.get("name"); + int age = (int) input.get("age"); + + input.put("transformedName", name.toUpperCase()); + input.put("transformedAge", age + 10); + + return input; + } +} diff --git a/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java b/apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java similarity index 98% rename from apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java rename to apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java index 6401fa4be2..4b93d40dac 100644 --- a/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java +++ b/apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java @@ -1,4 +1,4 @@ -package dynamicrouter; +package com.baeldung.dynamicrouter; import com.baeldung.dynamicrouter.DynamicRouterRoute; import org.apache.camel.RoutesBuilder; diff --git a/apache-libraries/README.md b/apache-libraries/README.md index 6fe09008dc..410c0a2b36 100644 --- a/apache-libraries/README.md +++ b/apache-libraries/README.md @@ -13,3 +13,5 @@ This module contains articles about various Apache libraries and utilities - [Introduction to Apache Curator](https://www.baeldung.com/apache-curator) - [A Quick Guide to Apache Geode](https://www.baeldung.com/apache-geode) - [Guide To Solr in Java With Apache SolrJ](https://www.baeldung.com/apache-solrj) + +- More articles: [[next -->]](../apache-libraries-2) \ No newline at end of file diff --git a/apache-spark/pom.xml b/apache-spark/pom.xml index fbb6e9ba5e..210ea4f28b 100644 --- a/apache-spark/pom.xml +++ b/apache-spark/pom.xml @@ -5,8 +5,8 @@ 4.0.0 apache-spark 1.0-SNAPSHOT - apache-spark jar + apache-spark com.baeldung diff --git a/apache-thrift/pom.xml b/apache-thrift/pom.xml index d2623f92e7..f5c5dec928 100644 --- a/apache-thrift/pom.xml +++ b/apache-thrift/pom.xml @@ -5,8 +5,8 @@ 4.0.0 apache-thrift 0.0.1-SNAPSHOT - apache-thrift pom + apache-thrift com.baeldung diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml index f4b6de8872..5dd56a1d68 100644 --- a/apache-velocity/pom.xml +++ b/apache-velocity/pom.xml @@ -5,8 +5,8 @@ 4.0.0 apache-velocity 0.1-SNAPSHOT - apache-velocity war + apache-velocity com.baeldung @@ -28,7 +28,7 @@ org.apache.httpcomponents httpclient - ${org.apache.httpcomponents.version} + ${httpclient.version} test @@ -60,7 +60,7 @@ - 4.5.2 + 4.5.2 1.7 2.0 diff --git a/aws-modules/aws-dynamodb/pom.xml b/aws-modules/aws-dynamodb/pom.xml index 199b9a187e..6d1ad5ad34 100644 --- a/aws-modules/aws-dynamodb/pom.xml +++ b/aws-modules/aws-dynamodb/pom.xml @@ -5,8 +5,8 @@ 4.0.0 aws-dynamodb 0.1.0-SNAPSHOT - aws-dynamodb jar + aws-dynamodb com.baeldung diff --git a/aws-modules/aws-lambda-modules/lambda-function/pom.xml b/aws-modules/aws-lambda-modules/lambda-function/pom.xml index 8c56aaabed..9a24802e3f 100644 --- a/aws-modules/aws-lambda-modules/lambda-function/pom.xml +++ b/aws-modules/aws-lambda-modules/lambda-function/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 lambda-function - 0.1.0-SNAPSHOT lambda-function + 0.1.0-SNAPSHOT jar diff --git a/aws-modules/aws-lambda-modules/pom.xml b/aws-modules/aws-lambda-modules/pom.xml index 9886ff58d2..a4b7197fee 100644 --- a/aws-modules/aws-lambda-modules/pom.xml +++ b/aws-modules/aws-lambda-modules/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 aws-lambda-modules - aws-lambda-modules pom + aws-lambda-modules com.baeldung diff --git a/aws-modules/aws-lambda-modules/shipping-tracker-lambda/ShippingFunction/pom.xml b/aws-modules/aws-lambda-modules/shipping-tracker-lambda/ShippingFunction/pom.xml index 74a21068ee..0f294fabeb 100644 --- a/aws-modules/aws-lambda-modules/shipping-tracker-lambda/ShippingFunction/pom.xml +++ b/aws-modules/aws-lambda-modules/shipping-tracker-lambda/ShippingFunction/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 ShippingFunction - 1.0 ShippingFunction + 1.0 jar diff --git a/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml b/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml index 8eb0879237..acc14b55ff 100644 --- a/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml +++ b/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml @@ -4,8 +4,8 @@ 4.0.0 helloworld ToDoFunction - 1.0 ToDoFunction + 1.0 jar diff --git a/aws-modules/aws-miscellaneous/pom.xml b/aws-modules/aws-miscellaneous/pom.xml index 8a90ec8cc9..2e42cff0c3 100644 --- a/aws-modules/aws-miscellaneous/pom.xml +++ b/aws-modules/aws-miscellaneous/pom.xml @@ -5,8 +5,8 @@ 4.0.0 aws-miscellaneous 0.1.0-SNAPSHOT - aws-miscellaneous jar + aws-miscellaneous com.baeldung diff --git a/aws-modules/aws-reactive/pom.xml b/aws-modules/aws-reactive/pom.xml index 7a425c44b4..0ff255d960 100644 --- a/aws-modules/aws-reactive/pom.xml +++ b/aws-modules/aws-reactive/pom.xml @@ -87,6 +87,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.version} diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md index f3b34b584e..36dd1b4bfd 100644 --- a/aws-modules/aws-s3/README.md +++ b/aws-modules/aws-s3/README.md @@ -12,3 +12,4 @@ This module contains articles about Simple Storage Service (S3) on AWS - [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object) - [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders) - [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object) +- [How to Mock Amazon S3 for Integration Test](https://www.baeldung.com/java-amazon-simple-storage-service-mock-testing) diff --git a/aws-modules/aws-s3/pom.xml b/aws-modules/aws-s3/pom.xml index f63158b889..09ab7649d6 100644 --- a/aws-modules/aws-s3/pom.xml +++ b/aws-modules/aws-s3/pom.xml @@ -5,8 +5,8 @@ 4.0.0 aws-s3 0.1.0-SNAPSHOT - aws-s3 jar + aws-s3 com.baeldung @@ -26,7 +26,6 @@ ${aws.java.sdk.version} test - commons-io commons-io @@ -56,7 +55,6 @@ ${com.adobe.testing.version} test - org.testcontainers junit-jupiter diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml index 6d5f3fb168..c6bf59c1b2 100644 --- a/aws-modules/pom.xml +++ b/aws-modules/pom.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 aws-modules + pom aws-modules @@ -12,16 +13,6 @@ 1.0.0-SNAPSHOT - - - com.amazonaws - aws-java-sdk-dynamodb - 1.12.523 - compile - - - pom - aws-app-sync aws-dynamodb @@ -31,6 +22,15 @@ aws-s3 + + + com.amazonaws + aws-java-sdk-dynamodb + 1.12.523 + compile + + + 1.12.331 2.24.9 diff --git a/azure/pom.xml b/azure/pom.xml index 6a06282a71..61ae0c7d68 100644 --- a/azure/pom.xml +++ b/azure/pom.xml @@ -5,8 +5,8 @@ 4.0.0 azure 0.1 - azure war + azure Demo project for Spring Boot on Azure diff --git a/checker-framework/pom.xml b/checker-framework/pom.xml index dd3a9fd28b..4fbeb73631 100644 --- a/checker-framework/pom.xml +++ b/checker-framework/pom.xml @@ -5,8 +5,8 @@ 4.0.0 checker-framework 1.0-SNAPSHOT - checker-framework jar + checker-framework com.baeldung diff --git a/core-java-modules/core-java-10/pom.xml b/core-java-modules/core-java-10/pom.xml index 40fd75ee02..2551b1aa96 100644 --- a/core-java-modules/core-java-10/pom.xml +++ b/core-java-modules/core-java-10/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-10 - core-java-10 jar + core-java-10 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-11-2/pom.xml b/core-java-modules/core-java-11-2/pom.xml index 4647814048..6de1fc5586 100644 --- a/core-java-modules/core-java-11-2/pom.xml +++ b/core-java-modules/core-java-11-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-11-2 - core-java-11-2 jar + core-java-11-2 com.baeldung @@ -15,11 +15,6 @@ - - com.google.guava - guava - ${guava.version} - org.mock-server mockserver-junit-jupiter diff --git a/core-java-modules/core-java-11-3/pom.xml b/core-java-modules/core-java-11-3/pom.xml index 9d21958cff..cbe980d881 100644 --- a/core-java-modules/core-java-11-3/pom.xml +++ b/core-java-modules/core-java-11-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-11-3 - core-java-11-3 jar + core-java-11-3 com.baeldung diff --git a/core-java-modules/core-java-11/pom.xml b/core-java-modules/core-java-11/pom.xml index 7092f4e53d..b3b0e440ca 100644 --- a/core-java-modules/core-java-11/pom.xml +++ b/core-java-modules/core-java-11/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-11 - core-java-11 jar + core-java-11 com.baeldung @@ -15,11 +15,6 @@ - - com.google.guava - guava - ${guava.version} - org.openjdk.jmh jmh-core diff --git a/core-java-modules/core-java-12/pom.xml b/core-java-modules/core-java-12/pom.xml index ae61bdfad0..c5496c2c29 100644 --- a/core-java-modules/core-java-12/pom.xml +++ b/core-java-modules/core-java-12/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-12 - core-java-12 jar + core-java-12 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-13/pom.xml b/core-java-modules/core-java-13/pom.xml index b8ec8cfdb9..dbbf3a8329 100644 --- a/core-java-modules/core-java-13/pom.xml +++ b/core-java-modules/core-java-13/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-13 - core-java-13 jar + core-java-13 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-14/pom.xml b/core-java-modules/core-java-14/pom.xml index 38f640762f..669d6587dc 100644 --- a/core-java-modules/core-java-14/pom.xml +++ b/core-java-modules/core-java-14/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-14 - core-java-14 jar + core-java-14 com.baeldung diff --git a/core-java-modules/core-java-15/pom.xml b/core-java-modules/core-java-15/pom.xml index 5f1ff1bbca..27f3f4019b 100644 --- a/core-java-modules/core-java-15/pom.xml +++ b/core-java-modules/core-java-15/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-15 - core-java-15 jar + core-java-15 com.baeldung.core-java-modules @@ -13,7 +13,6 @@ 0.0.1-SNAPSHOT - org.apache.commons diff --git a/core-java-modules/core-java-16/pom.xml b/core-java-modules/core-java-16/pom.xml index c439a5bf12..8afd6f3dc7 100644 --- a/core-java-modules/core-java-16/pom.xml +++ b/core-java-modules/core-java-16/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-16 - core-java-16 jar + core-java-16 com.baeldung diff --git a/core-java-modules/core-java-17/pom.xml b/core-java-modules/core-java-17/pom.xml index aae19ff85e..f8ed207f6c 100644 --- a/core-java-modules/core-java-17/pom.xml +++ b/core-java-modules/core-java-17/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-17 - core-java-17 jar + core-java-17 com.baeldung diff --git a/core-java-modules/core-java-18/pom.xml b/core-java-modules/core-java-18/pom.xml index 78552d2c70..b9bd8982ab 100644 --- a/core-java-modules/core-java-18/pom.xml +++ b/core-java-modules/core-java-18/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-18 - core-java-18 jar + core-java-18 com.baeldung diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java new file mode 100644 index 0000000000..0d5f5c486a --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java @@ -0,0 +1,44 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.stream.Stream; + +import com.baeldung.inetspi.providers.CustomAddressResolverImpl; + +public class InetAddressSPI { + public String usingGetByName(String host) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByName(host); + return inetAddress.getHostAddress(); + } + + public String[] usingGetAllByName(String host) throws UnknownHostException { + InetAddress[] inetAddresses = InetAddress.getAllByName(host); + return Arrays.stream(inetAddresses).map(InetAddress::getHostAddress).toArray(String[]::new); + } + + public String usingGetByIp(byte[] ip) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByAddress(ip); + + return inetAddress.getHostName(); + } + + public String usingGetByIpAndReturnsCannonName(byte[] ip) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByAddress(ip); + + return inetAddress.getCanonicalHostName(); + } + + public String getHostUsingCustomImpl(byte[] ip) throws UnknownHostException { + + CustomAddressResolverImpl imp = new CustomAddressResolverImpl(); + return imp.get(null).lookupByAddress(ip); + } + + public Stream getIpUsingCustomImpl(String host) throws UnknownHostException { + + CustomAddressResolverImpl imp = new CustomAddressResolverImpl(); + return imp.get(null).lookupByName(host, null); + } +} diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java new file mode 100644 index 0000000000..db15f6a8d4 --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java @@ -0,0 +1,56 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Logger; +import java.util.stream.Stream; + +public class Registry { + private final Map> registry; + + private static final Logger LOGGER = Logger.getLogger(Registry.class.getName()); + + public Registry() { + registry = loadMapWithData(); + } + + public Stream getAddressesfromHost(String host) throws UnknownHostException { + LOGGER.info("Performing Forward Lookup for HOST : " + host); + if (!registry.containsKey(host)) { + throw new UnknownHostException("Missing Host information in Resolver"); + } + return registry.get(host) + .stream() + .map(add -> constructInetAddress(host, add)) + .filter(Objects::nonNull); + } + + public String getHostFromAddress(byte[] arr) throws UnknownHostException { + LOGGER.info("Performing Reverse Lookup for Address : " + Arrays.toString(arr)); + for (Map.Entry> entry : registry.entrySet()) { + if (entry.getValue() + .stream() + .anyMatch(ba -> Arrays.equals(ba, arr))) { + return entry.getKey(); + } + } + throw new UnknownHostException("Address Not Found"); + } + + private Map> loadMapWithData() { + return Map.of("baeldung-local.org", List.of(new byte[] { 1, 2, 3, 4 })); + } + + private static InetAddress constructInetAddress(String host, byte[] address) { + try { + return InetAddress.getByAddress(host, address); + } catch (UnknownHostException unknownHostException) { + return null; + } + } + +} diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java new file mode 100644 index 0000000000..0b1849c3f9 --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java @@ -0,0 +1,42 @@ +package com.baeldung.inetspi.providers; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.spi.InetAddressResolver; +import java.net.spi.InetAddressResolverProvider; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Stream; + +import com.baeldung.inetspi.Registry; + +public class CustomAddressResolverImpl extends InetAddressResolverProvider { + + private static Logger LOGGER = Logger.getLogger(CustomAddressResolverImpl.class.getName()); + + private static Registry registry = new Registry(); + + @Override + public InetAddressResolver get(Configuration configuration) { + LOGGER.info("Using Custom Address Resolver :: " + this.name()); + LOGGER.info("Registry initialised"); + return new InetAddressResolver() { + @Override + public Stream lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException { + return registry.getAddressesfromHost(host); + } + + @Override + public String lookupByAddress(byte[] addr) throws UnknownHostException { + return registry.getHostFromAddress(addr); + } + }; + } + + @Override + public String name() { + return "CustomInternetAddressResolverImpl"; + } +} diff --git a/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java b/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java new file mode 100644 index 0000000000..ad8e6f0e54 --- /dev/null +++ b/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.stream.Stream; + +import org.junit.Assert; +import org.junit.Test; + +public class InetAddressSPIUnitTest { + @Test + public void givenInetAddress_whenUsingInetAddress_thenPerformResolution() throws UnknownHostException { + InetAddressSPI spi = new InetAddressSPI(); + Assert.assertNotNull(spi.usingGetByName("www.google.com")); + Assert.assertTrue(spi.usingGetAllByName("www.google.com").length > 1); + Assert.assertNotNull(spi.usingGetByIp(InetAddress.getByName("www.google.com") + .getAddress())); + Assert.assertNotNull(spi.usingGetByIpAndReturnsCannonName(InetAddress.getByName("www.google.com") + .getAddress())); + } + + @Test + public void givenCustomInetAddressImplementation_whenUsingInetAddress_thenPerformResolution() throws UnknownHostException { + InetAddressSPI spi = new InetAddressSPI(); + Assert.assertEquals("baeldung-local.org", spi.getHostUsingCustomImpl(new byte[] { 1, 2, 3, 4 })); + Stream response = spi.getIpUsingCustomImpl("baeldung-local.org"); + Assert.assertArrayEquals(new byte[] { 1, 2, 3, 4 }, response.findFirst() + .get() + .getAddress()); + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java new file mode 100644 index 0000000000..7b64a382bc --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java @@ -0,0 +1,32 @@ +package com.baeldung.java21; + +public class PatternCaseLabels { + + static String processInputOld(String input) { + String output; + switch (input) { + case null -> output = "Oops, null"; + case String s -> { + if ("Yes".equalsIgnoreCase(s)) { + output = "It's Yes"; + } else if ("No".equalsIgnoreCase(s)) { + output = "It's No"; + } else { + output = "Try Again"; + } + } + } + return output; + } + + static String processInputNew(String input) { + String output; + switch (input) { + case null -> output = "Oops, null"; + case String s when "Yes".equalsIgnoreCase(s) -> output = "It's Yes"; + case String s when "No".equalsIgnoreCase(s) -> output = "It's No"; + case String s -> output = "Try Again"; + } + return output; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java new file mode 100644 index 0000000000..e06539f888 --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java @@ -0,0 +1,36 @@ +package com.baeldung.java21; + +public class RecordPattern { + + record Point(int x, int y) {} + + public static int beforeRecordPattern(Object obj) { + int sum = 0; + if(obj instanceof Point p) { + int x = p.x(); + int y = p.y(); + sum = x+y; + } + return sum; + } + + public static int afterRecordPattern(Object obj) { + if(obj instanceof Point(int x, int y)) { + return x+y; + } + return 0; + } + + enum Color {RED, GREEN, BLUE} + + record ColoredPoint(Point point, Color color) {} + + record RandomPoint(ColoredPoint cp) {} + + public static Color getRamdomPointColor(RandomPoint r) { + if(r instanceof RandomPoint(ColoredPoint cp)) { + return cp.color(); + } + return null; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java new file mode 100644 index 0000000000..19dffd001b --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java @@ -0,0 +1,9 @@ +package com.baeldung.java21; + +public class StringTemplates { + + public String getStringTemplate() { + String name = "Baeldung"; + return STR."Welcome to \{name}"; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java new file mode 100644 index 0000000000..9ef7527415 --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java @@ -0,0 +1,56 @@ +package com.baeldung.java21; + +public class SwitchPattern { + + static class Account{ + double getBalance() { + return 0; + } + } + + static class SavingsAccount extends Account { + @Override + double getBalance() { + return 100; + } + } + + static class TermAccount extends Account { + @Override + double getBalance() { + return 1000; + } + } + static class CurrentAccount extends Account { + @Override + double getBalance() { + return 10000; + } + } + + static double getBalanceWithOutSwitchPattern(Account account) { + double balance = 0; + if(account instanceof SavingsAccount sa) { + balance = sa.getBalance(); + } + else if(account instanceof TermAccount ta) { + balance = ta.getBalance(); + } + else if(account instanceof CurrentAccount ca) { + balance = ca.getBalance(); + } + return balance; + } + + static double getBalanceWithSwitchPattern(Account account) { + double result; + switch (account) { + case null -> throw new IllegalArgumentException("Oops, account is null"); + case SavingsAccount sa -> result = sa.getBalance(); + case TermAccount ta -> result = ta.getBalance(); + case CurrentAccount ca -> result = ca.getBalance(); + default -> result = account.getBalance(); + } + return result; + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java new file mode 100644 index 0000000000..07b11ff50c --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class PatternCaseLabelsUnitTest { + + @Test + void whenProcessInputOldWayWithYes_thenReturnOutput() { + assertEquals("It's Yes", PatternCaseLabels.processInputOld("Yes")); + } + + @Test + void whenProcessInputOldWayWithNo_thenReturnOutput() { + assertEquals("It's No", PatternCaseLabels.processInputOld("No")); + } + + @Test + void whenProcessInputOldWayWithNull_thenReturnOutput() { + assertEquals("Oops, null", PatternCaseLabels.processInputOld(null)); + } + + @Test + void whenProcessInputOldWayWithInvalidOption_thenReturnOutput() { + assertEquals("Try Again", PatternCaseLabels.processInputOld("Invalid Option")); + } + + @Test + void whenProcessInputNewWayWithYes_thenReturnOutput() { + assertEquals("It's Yes", PatternCaseLabels.processInputNew("Yes")); + } + + @Test + void whenProcessInputNewWayWithNo_thenReturnOutput() { + assertEquals("It's No", PatternCaseLabels.processInputNew("No")); + } + + @Test + void whenProcessInputNewWayWithNull_thenReturnOutput() { + assertEquals("Oops, null", PatternCaseLabels.processInputNew(null)); + } + + @Test + void whenProcessInputNewWayWithInvalidOption_thenReturnOutput() { + assertEquals("Try Again", PatternCaseLabels.processInputNew("Invalid Option")); + } + +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java new file mode 100644 index 0000000000..da8f4395e0 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +import com.baeldung.java21.RecordPattern.Color; +import com.baeldung.java21.RecordPattern.ColoredPoint; +import com.baeldung.java21.RecordPattern.Point; +import com.baeldung.java21.RecordPattern.RandomPoint; + +class RecordPatternUnitTest { + + @Test + void whenNoRecordPattern_thenReturnOutput() { + assertEquals(5, RecordPattern.beforeRecordPattern(new Point(2, 3))); + } + + @Test + void whenRecordPattern_thenReturnOutput() { + assertEquals(5, RecordPattern.afterRecordPattern(new Point(2, 3))); + } + + @Test + void whenRecordPattern_thenReturnColorOutput() { + ColoredPoint coloredPoint = new ColoredPoint(new Point(2, 3), Color.GREEN); + RandomPoint randomPoint = new RandomPoint(coloredPoint); + assertEquals(Color.GREEN, RecordPattern.getRamdomPointColor(randomPoint)); + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java new file mode 100644 index 0000000000..340e9b54d9 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java @@ -0,0 +1,13 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class StringTemplateUnitTest { + + @Test + void whenNoSwitchPattern_thenReturnSavingsAccountBalance() { + StringTemplates stringTemplates = new StringTemplates(); + assertEquals("Welcome to Baeldung", stringTemplates.getStringTemplate()); + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java new file mode 100644 index 0000000000..7429b303e9 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class SwitchPatternUnitTest { + + @Test + void whenNoSwitchPattern_thenReturnSavingsAccountBalance() { + SwitchPattern.SavingsAccount savingsAccount = new SwitchPattern.SavingsAccount(); + assertEquals(100, SwitchPattern.getBalanceWithOutSwitchPattern(savingsAccount), 0); + } + + @Test + void whenSwitchPattern_thenReturnSavingsAccountBalance() { + SwitchPattern.SavingsAccount savingsAccount = new SwitchPattern.SavingsAccount(); + assertEquals(100, SwitchPattern.getBalanceWithSwitchPattern(savingsAccount), 0); + } +} diff --git a/core-java-modules/core-java-8-datetime-2/README.md b/core-java-modules/core-java-8-datetime-2/README.md index e689e7257f..04461663e3 100644 --- a/core-java-modules/core-java-8-datetime-2/README.md +++ b/core-java-modules/core-java-8-datetime-2/README.md @@ -13,4 +13,5 @@ - [Format LocalDate to ISO 8601 With T and Z](https://www.baeldung.com/java-format-localdate-iso-8601-t-z) - [Check if Two Date Ranges Overlap](https://www.baeldung.com/java-check-two-date-ranges-overlap) - [Difference between ZoneOffset.UTC and ZoneId.of(“UTC”)](https://www.baeldung.com/java-zoneoffset-utc-zoneid-of) +- [Check if a Given Time Lies Between Two Times Regardless of Date](https://www.baeldung.com/java-check-between-two-times) - [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1) diff --git a/core-java-modules/core-java-8-datetime-2/pom.xml b/core-java-modules/core-java-8-datetime-2/pom.xml index 168177c87a..727ae91573 100644 --- a/core-java-modules/core-java-8-datetime-2/pom.xml +++ b/core-java-modules/core-java-8-datetime-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-8-datetime-2 - core-java-8-datetime-2 jar + core-java-8-datetime-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/checkiftimebetweentwotimes/CheckIfTimeBetweenTwoTimesUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/checkiftimebetweentwotimes/CheckIfTimeBetweenTwoTimesUnitTest.java new file mode 100644 index 0000000000..1ffddaa241 --- /dev/null +++ b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/checkiftimebetweentwotimes/CheckIfTimeBetweenTwoTimesUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.checkiftimebetweentwotimes; + +import org.junit.Test; + +import java.time.LocalTime; +import java.util.Calendar; +import java.util.Date; + +import static org.junit.Assert.assertTrue; + +public class CheckIfTimeBetweenTwoTimesUnitTest { + private LocalTime startTime = LocalTime.parse("09:00:00"); + private LocalTime endTime = LocalTime.parse("17:00:00"); + private LocalTime targetTime = LocalTime.parse("12:30:00"); + + @Test + public void givenLocalTime_whenUsingIsAfterIsBefore_thenTimeIsBetween() { + assertTrue(!targetTime.isBefore(startTime) && !targetTime.isAfter(endTime)); + } + + @Test + public void givenLocalTime_whenUsingCompareTo_thenTimeIsBetween() { + assertTrue(targetTime.compareTo(startTime) >= 0 && targetTime.compareTo(endTime) <= 0); + } + + @Test + public void givenDate_whenUsingAfterBefore_thenTimeIsBetween() { + Calendar startCalendar = Calendar.getInstance(); + startCalendar.set(Calendar.HOUR_OF_DAY, 9); + startCalendar.set(Calendar.MINUTE, 0); + Date startTime = startCalendar.getTime(); + + Calendar endCalendar = Calendar.getInstance(); + endCalendar.set(Calendar.HOUR_OF_DAY, 17); + endCalendar.set(Calendar.MINUTE, 0); + Date endTime = endCalendar.getTime(); + + Calendar targetCalendar = Calendar.getInstance(); + targetCalendar.set(Calendar.HOUR_OF_DAY, 12); + targetCalendar.set(Calendar.MINUTE, 30); + Date targetTime = targetCalendar.getTime(); + + assertTrue(!targetTime.before(startTime) && !targetTime.after(endTime)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-8-datetime/pom.xml b/core-java-modules/core-java-8-datetime/pom.xml index cff27c9d44..8cf48fd467 100644 --- a/core-java-modules/core-java-8-datetime/pom.xml +++ b/core-java-modules/core-java-8-datetime/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-8-datetime - core-java-8-datetime jar + core-java-8-datetime com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-9-jigsaw/README.md b/core-java-modules/core-java-9-jigsaw/README.md index 73905e6033..b1630f04fc 100644 --- a/core-java-modules/core-java-9-jigsaw/README.md +++ b/core-java-modules/core-java-9-jigsaw/README.md @@ -5,7 +5,7 @@ This module contains articles about Project Jigsaw and the Java Platform Module ### Relevant Articles: - [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity) -- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity) +- [A Guide to Java Modularity](https://www.baeldung.com/java-modularity) - [Java 9 java.lang.Module API](https://www.baeldung.com/java-9-module-api) - [Java 9 Illegal Reflective Access Warning](https://www.baeldung.com/java-illegal-reflective-access) - [Java Modularity and Unit Testing](https://www.baeldung.com/java-modularity-unit-testing) diff --git a/core-java-modules/core-java-9-jigsaw/library-core/pom.xml b/core-java-modules/core-java-9-jigsaw/library-core/pom.xml index 415c7fb053..d1be46fd63 100644 --- a/core-java-modules/core-java-9-jigsaw/library-core/pom.xml +++ b/core-java-modules/core-java-9-jigsaw/library-core/pom.xml @@ -3,20 +3,14 @@ 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 + library-core + com.baeldung.core-java-modules core-java-9-jigsaw 0.0.1-SNAPSHOT - library-core - - - 19 - 19 - UTF-8 - - org.junit.jupiter @@ -52,4 +46,11 @@ + + + 19 + 19 + UTF-8 + + \ No newline at end of file diff --git a/core-java-modules/core-java-9-jigsaw/pom.xml b/core-java-modules/core-java-9-jigsaw/pom.xml index 4afe2ae31a..6bbafeabae 100644 --- a/core-java-modules/core-java-9-jigsaw/pom.xml +++ b/core-java-modules/core-java-9-jigsaw/pom.xml @@ -4,8 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-9-jigsaw - core-java-9-jigsaw pom + core-java-9-jigsaw + library-core diff --git a/core-java-modules/core-java-9-streams/pom.xml b/core-java-modules/core-java-9-streams/pom.xml index 903194b3b3..c8a6a22797 100644 --- a/core-java-modules/core-java-9-streams/pom.xml +++ b/core-java-modules/core-java-9-streams/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-9-streams - core-java-9-streams jar + core-java-9-streams com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-annotations/pom.xml b/core-java-modules/core-java-annotations/pom.xml index 6b1b9d802f..8796717310 100644 --- a/core-java-modules/core-java-annotations/pom.xml +++ b/core-java-modules/core-java-annotations/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-annotations - core-java-annotations jar + core-java-annotations com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-arrays-convert/pom.xml b/core-java-modules/core-java-arrays-convert/pom.xml index 480e1b3f07..eeabd1e360 100644 --- a/core-java-modules/core-java-arrays-convert/pom.xml +++ b/core-java-modules/core-java-arrays-convert/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-convert - core-java-arrays-convert jar + core-java-arrays-convert core-java-modules @@ -20,4 +20,5 @@ ${commons-lang3.version} + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-guides/pom.xml b/core-java-modules/core-java-arrays-guides/pom.xml index 12da6b2145..a79d3a59e7 100644 --- a/core-java-modules/core-java-arrays-guides/pom.xml +++ b/core-java-modules/core-java-arrays-guides/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-guides - core-java-arrays-guides jar + core-java-arrays-guides core-java-modules diff --git a/core-java-modules/core-java-arrays-multidimensional/pom.xml b/core-java-modules/core-java-arrays-multidimensional/pom.xml index d314b07d85..bb37cd3f16 100644 --- a/core-java-modules/core-java-arrays-multidimensional/pom.xml +++ b/core-java-modules/core-java-arrays-multidimensional/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-multidimensional - core-java-arrays-multidimensional jar + core-java-arrays-multidimensional core-java-modules diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/README.md b/core-java-modules/core-java-arrays-operations-advanced-2/README.md index 88bda5c6d7..e762508bcd 100644 --- a/core-java-modules/core-java-arrays-operations-advanced-2/README.md +++ b/core-java-modules/core-java-arrays-operations-advanced-2/README.md @@ -2,3 +2,4 @@ - [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item) - [Find the Equilibrium Indexes of an Array in Java](https://www.baeldung.com/java-equilibrium-index-array) - [Moves Zeros to the End of an Array in Java](https://www.baeldung.com/java-array-sort-move-zeros-end) +- [Finding the Majority Element of an Array in Java](https://www.baeldung.com/java-array-find-majority-element) diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml index a0ae2398a4..20bdb928ec 100644 --- a/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml +++ b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-operations-advanced-2 - core-java-arrays-operations-advanced-2 jar + core-java-arrays-operations-advanced-2 core-java-modules diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/majorityelement/FindMajorityElement.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/majorityelement/FindMajorityElement.java new file mode 100644 index 0000000000..04da571a6c --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/majorityelement/FindMajorityElement.java @@ -0,0 +1,95 @@ +package com.baeldung.majorityelement; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class FindMajorityElement { + + public static Integer findMajorityElementUsingForLoop(int[] nums) { + int majorityThreshold = nums.length / 2; + Integer majorityElement = null; + for (int i = 0; i < nums.length; i++) { + int count = 0; + for (int j = 0; j < nums.length; j++) { + if (nums[i] == nums[j]) { + count++; + } + } + if (count > majorityThreshold) { + return majorityElement = nums[i]; + } + } + return majorityElement; + } + + public static Integer findMajorityElementUsingSorting(int[] nums) { + Arrays.sort(nums); + int majorityThreshold = nums.length / 2; + int count = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] == nums[majorityThreshold]) { + count++; + } + + if (count > majorityThreshold) { + return nums[majorityThreshold]; + } + } + return null; + } + + public static Integer findMajorityElementUsingHashMap(int[] nums) { + Map frequencyMap = new HashMap<>(); + + for (int num : nums) { + frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); + } + + int majorityThreshold = nums.length / 2; + for (Map.Entry entry : frequencyMap.entrySet()) { + if (entry.getValue() > majorityThreshold) { + return entry.getKey(); + } + } + return null; + } + + public static Integer findMajorityElementUsingMooreVoting(int[] nums) { + int majorityThreshold = nums.length / 2; + int candidate = nums[0]; + int count = 1; + + for (int i = 1; i < nums.length; i++) { + if (count == 0) { + candidate = nums[i]; + count = 1; + } else if (candidate == nums[i]) { + count++; + } else { + count--; + } + + System.out.println("Iteration " + i + ": [candidate - " + candidate + ", count - " + count + ", element - " + nums[i] + "]"); + } + + count = 0; + for (int num : nums) { + if (num == candidate) { + count++; + } + } + return count > majorityThreshold ? candidate : null; + } + + public static void main(String[] args) { + int[] nums = { 2, 3, 2, 4, 2, 5, 2 }; + Integer majorityElement = findMajorityElementUsingMooreVoting(nums); + + if (majorityElement != null) { + System.out.println("Majority element with maximum occurrences: " + majorityElement); + } else { + System.out.println("No majority element found"); + } + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/majorityelement/FindMajorityElementUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/majorityelement/FindMajorityElementUnitTest.java new file mode 100644 index 0000000000..4e3abf9a49 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/majorityelement/FindMajorityElementUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.majorityelement; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class FindMajorityElementUnitTest { + + @Test + void givenArrayWithMajorityElement_WhenUsingForLoop_ThenReturnFound() { + int[] nums = { 2, 3, 2, 4, 2, 5, 2 }; + Integer result = FindMajorityElement.findMajorityElementUsingForLoop(nums); + assertEquals(2, result); + } + + @Test + void givenArrayWithoutMajorityElement_WhenUsingForLoop_ThenNotFound() { + int[] nums = { 2, 2, 3, 3 }; + Integer result = FindMajorityElement.findMajorityElementUsingForLoop(nums); + assertEquals(null, result); + } + + @Test + public void givenArrayWithMajorityElement_WhenUsingSorting_ThenReturnFound() { + int[] nums = { 2, 3, 2, 4, 2, 5, 2 }; + Integer result = FindMajorityElement.findMajorityElementUsingSorting(nums); + assertEquals(2, result); + } + + @Test + public void givenArrayWithoutMajorityElement_WhenUsingSorting_ThenNotFound() { + int[] nums = { 2, 2, 3, 3 }; + Integer result = FindMajorityElement.findMajorityElementUsingSorting(nums); + assertEquals(null, result); + } + + @Test + void givenArrayWithMajorityElement_WhenUsingHashMap_ThenReturnFound() { + int[] nums = { 2, 3, 2, 4, 2, 5, 2 }; + Integer result = FindMajorityElement.findMajorityElementUsingHashMap(nums); + assertEquals(2, result); + } + + @Test + void givenArrayWithoutMajorityElement_WhenUsingHashMap_ThenNotFound() { + int[] nums = { 2, 2, 3, 3 }; + Integer result = FindMajorityElement.findMajorityElementUsingHashMap(nums); + assertEquals(null, result); + } + + @Test + void givenArrayWithMajorityElement_WhenUsingMooreVoting_ThenReturnFound() { + int[] nums = { 2, 3, 2, 4, 2, 5, 2 }; + Integer result = FindMajorityElement.findMajorityElementUsingMooreVoting(nums); + assertEquals(2, result); + } + + @Test + void givenArrayWithoutMajorityElement_WhenUsingMooreVoting_ThenNotFound() { + int[] nums = { 2, 2, 3, 3 }; + Integer result = FindMajorityElement.findMajorityElementUsingMooreVoting(nums); + assertEquals(null, result); + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/pom.xml b/core-java-modules/core-java-arrays-operations-advanced/pom.xml index 265577f75e..fad94672a1 100644 --- a/core-java-modules/core-java-arrays-operations-advanced/pom.xml +++ b/core-java-modules/core-java-arrays-operations-advanced/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-operations-advanced - core-java-arrays-operations-advanced jar + core-java-arrays-operations-advanced core-java-modules diff --git a/core-java-modules/core-java-arrays-operations-basic-2/pom.xml b/core-java-modules/core-java-arrays-operations-basic-2/pom.xml index 7257a39462..354da6d7ff 100644 --- a/core-java-modules/core-java-arrays-operations-basic-2/pom.xml +++ b/core-java-modules/core-java-arrays-operations-basic-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-operations-basic-2 - core-java-arrays-operations-basic-2 jar + core-java-arrays-operations-basic-2 core-java-modules diff --git a/core-java-modules/core-java-arrays-operations-basic/pom.xml b/core-java-modules/core-java-arrays-operations-basic/pom.xml index 6517b2efb9..6ce807ddc4 100644 --- a/core-java-modules/core-java-arrays-operations-basic/pom.xml +++ b/core-java-modules/core-java-arrays-operations-basic/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-operations-basic - core-java-arrays-operations-basic jar + core-java-arrays-operations-basic core-java-modules diff --git a/core-java-modules/core-java-arrays-sorting/pom.xml b/core-java-modules/core-java-arrays-sorting/pom.xml index 82e3f659fc..a67cd7b751 100644 --- a/core-java-modules/core-java-arrays-sorting/pom.xml +++ b/core-java-modules/core-java-arrays-sorting/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-arrays-sorting - core-java-arrays-sorting jar + core-java-arrays-sorting core-java-modules diff --git a/core-java-modules/core-java-booleans/pom.xml b/core-java-modules/core-java-booleans/pom.xml index 3b0c28208f..6ca2a6b1a2 100644 --- a/core-java-modules/core-java-booleans/pom.xml +++ b/core-java-modules/core-java-booleans/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-booleans - core-java-booleans jar + core-java-booleans com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-char/pom.xml b/core-java-modules/core-java-char/pom.xml index eb6cbee952..86d50436d2 100644 --- a/core-java-modules/core-java-char/pom.xml +++ b/core-java-modules/core-java-char/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-char - core-java-char jar + core-java-char com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-2/pom.xml b/core-java-modules/core-java-collections-2/pom.xml index e78f7b5dda..b06a9e5c8c 100644 --- a/core-java-modules/core-java-collections-2/pom.xml +++ b/core-java-modules/core-java-collections-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-2 - core-java-collections-2 jar + core-java-collections-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-3/pom.xml b/core-java-modules/core-java-collections-3/pom.xml index 373dc9db14..e24b58d62b 100644 --- a/core-java-modules/core-java-collections-3/pom.xml +++ b/core-java-modules/core-java-collections-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-3 - core-java-collections-3 jar + core-java-collections-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-4/pom.xml b/core-java-modules/core-java-collections-4/pom.xml index 1e54d65e35..696bc52335 100644 --- a/core-java-modules/core-java-collections-4/pom.xml +++ b/core-java-modules/core-java-collections-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-4 - core-java-collections-4 jar + core-java-collections-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-5/pom.xml b/core-java-modules/core-java-collections-5/pom.xml index 06d872ec37..939e479ba1 100644 --- a/core-java-modules/core-java-collections-5/pom.xml +++ b/core-java-modules/core-java-collections-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-5 - core-java-collections-5 jar + core-java-collections-5 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/immutables/ImmutableCollectionsUnitTest.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/immutables/ImmutableCollectionsUnitTest.java new file mode 100644 index 0000000000..6daec6d959 --- /dev/null +++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/immutables/ImmutableCollectionsUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.immutables; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +class ImmutableCollectionsUnitTest { + + @Test + void givenUnmodifiableMap_whenPutNewEntry_thenThrowsUnsupportedOperationException() { + Map modifiableMap = new HashMap<>(); + modifiableMap.put("name1", "Michael"); + modifiableMap.put("name2", "Harry"); + + Map unmodifiableMap = Collections.unmodifiableMap(modifiableMap); + + assertThrows(UnsupportedOperationException.class, () -> unmodifiableMap.put("name3", "Micky")); + } + + @Test + void givenUnmodifiableMap_whenPutNewEntryUsingOriginalReference_thenSuccess() { + Map modifiableMap = new HashMap<>(); + modifiableMap.put("name1", "Michael"); + modifiableMap.put("name2", "Harry"); + + Map unmodifiableMap = Collections.unmodifiableMap(modifiableMap); + modifiableMap.put("name3", "Micky"); + + assertEquals(modifiableMap, unmodifiableMap); + assertTrue(unmodifiableMap.containsKey("name3")); + } + + @Test + void givenImmutableMap_whenPutNewEntry_thenThrowsUnsupportedOperationException() { + Map immutableMap = Map.of("name1", "Michael", "name2", "Harry"); + + assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("name3", "Micky")); + } + + @Test + void givenImmutableMap_whenUsecopyOf_thenExceptionOnPut() { + Map immutableMap = Map.of("name1", "Michael", "name2", "Harry"); + Map copyOfImmutableMap = Map.copyOf(immutableMap); + + assertThrows(UnsupportedOperationException.class, () -> copyOfImmutableMap.put("name3", "Micky")); + } +} + diff --git a/core-java-modules/core-java-collections-array-list-2/README.md b/core-java-modules/core-java-collections-array-list-2/README.md index 575e0dbb07..aec8b90fb5 100644 --- a/core-java-modules/core-java-collections-array-list-2/README.md +++ b/core-java-modules/core-java-collections-array-list-2/README.md @@ -4,3 +4,4 @@ This module contains articles about the Java ArrayList collection ### Relevant Articles: - [Create an ArrayList with Multiple Object Types](https://www.baeldung.com/java-arraylist-multiple-object-types) +- [Finding the Peak Elements of a List](https://www.baeldung.com/java-list-find-peak) diff --git a/core-java-modules/core-java-collections-array-list-2/pom.xml b/core-java-modules/core-java-collections-array-list-2/pom.xml index 901a4f5c75..b436324dca 100644 --- a/core-java-modules/core-java-collections-array-list-2/pom.xml +++ b/core-java-modules/core-java-collections-array-list-2/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-array-list-2 - core-java-collections-array-list-2 jar + core-java-collections-array-list-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/MultiplePeakFinder.java b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/MultiplePeakFinder.java new file mode 100644 index 0000000000..f8e13ee86e --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/MultiplePeakFinder.java @@ -0,0 +1,40 @@ +package com.baeldung.peakelements; + +import java.util.ArrayList; +import java.util.List; + +public class MultiplePeakFinder { + + public static List findPeaks(int[] arr) { + + List peaks = new ArrayList<>(); + + if (arr == null || arr.length == 0) { + return peaks; + } + findPeakElements(arr, 0, arr.length - 1, peaks, arr.length); + return peaks; + } + + private static void findPeakElements(int[] arr, int low, int high, List peaks, int length) { + + if (low > high) { + return; + } + + int mid = low + (high - low) / 2; + + boolean isPeak = (mid == 0 || arr[mid] > arr[mid - 1]) && (mid == length - 1 || arr[mid] > arr[mid + 1]); + boolean isFirstInSequence = mid > 0 && arr[mid] == arr[mid - 1] && arr[mid] > arr[mid + 1]; + + if (isPeak || isFirstInSequence) { + + if (!peaks.contains(arr[mid])) { + peaks.add(arr[mid]); + } + } + + findPeakElements(arr, low, mid - 1, peaks, length); + findPeakElements(arr, mid + 1, high, peaks, length); + } +} diff --git a/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/PeakElementFinder.java b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/PeakElementFinder.java new file mode 100644 index 0000000000..857ae3b1b2 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/PeakElementFinder.java @@ -0,0 +1,44 @@ +package com.baeldung.peakelements; + +import java.util.ArrayList; +import java.util.List; + +public class PeakElementFinder { + public List findPeakElements(int[] arr) { + int n = arr.length; + List peaks = new ArrayList<>(); + + if (n == 0) { + return peaks; + } + + for (int i = 0; i < n; i++) { + if (isPeak(arr, i, n)) { + peaks.add(arr[i]); + } + + while (i < n - 1 && arr[i] == arr[i + 1]) { + i++; + } + } + + return peaks; + } + + private boolean isPeak(int[] arr, int index, int n) { + if (index == 0) { + return n > 1 ? arr[index] >= arr[index + 1] : true; + } else if (index == n - 1) { + return arr[index] >= arr[index - 1]; + } else if (arr[index] == arr[index + 1] && arr[index] > arr[index - 1]) { + int i = index; + + while (i < n - 1 && arr[i] == arr[i + 1]) { + i++; + } + return i == n - 1 || arr[i] > arr[i + 1]; + } else { + return arr[index] >= arr[index - 1] && arr[index] >= arr[index + 1]; + } + } +} diff --git a/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/SinglePeakFinder.java b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/SinglePeakFinder.java new file mode 100644 index 0000000000..f7b7cfc72b --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/peakelements/SinglePeakFinder.java @@ -0,0 +1,30 @@ +package com.baeldung.peakelements; + +import java.util.OptionalInt; + +public class SinglePeakFinder { + public static OptionalInt findSinglePeak(int[] arr) { + int n = arr.length; + + if (n < 2) { + return n == 0 ? OptionalInt.empty() : OptionalInt.of(arr[0]); + } + + if (arr[0] >= arr[1]) { + return OptionalInt.of(arr[0]); + } + + for (int i = 1; i < n - 1; i++) { + if (arr[i] >= arr[i - 1] && arr[i] >= arr[i + 1]) { + return OptionalInt.of(arr[i]); + } + } + + if (arr[n - 1] >= arr[n - 2]) { + return OptionalInt.of(arr[n - 1]); + } + + return OptionalInt.empty(); + } +} + diff --git a/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/MultiplePeakFinderUnitTest.java b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/MultiplePeakFinderUnitTest.java new file mode 100644 index 0000000000..bc145c654d --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/MultiplePeakFinderUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.peakelements; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class MultiplePeakFinderUnitTest { + + @Test + void findPeaks_givenArrayOfIntegers_whenValidInput_thenReturnsCorrectPeaks() { + MultiplePeakFinder finder = new MultiplePeakFinder(); + int[] array = {1, 13, 7, 0, 4, 1, 4, 45, 50}; + List peaks = finder.findPeaks(array); + + assertEquals(3, peaks.size()); + assertTrue(peaks.contains(4)); + assertTrue(peaks.contains(13)); + assertTrue(peaks.contains(50)); + } +} + diff --git a/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/PeakElementFinderUnitTest.java b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/PeakElementFinderUnitTest.java new file mode 100644 index 0000000000..fc521272b4 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/PeakElementFinderUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.peakelements; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class PeakElementFinderUnitTest { + + @Test + void findPeakElement_givenArrayOfIntegers_whenValidInput_thenReturnsCorrectPeak() { + PeakElementFinder finder = new PeakElementFinder(); + int[] array = {1, 2, 3, 2, 1}; + List peaks = finder.findPeakElements(array); + assertEquals(1, peaks.size()); + assertTrue(peaks.contains(3)); + } + + @Test + void findPeakElement_givenArrayOfIntegers_whenNoPeaks_thenReturnsEmptyList() { + PeakElementFinder finder = new PeakElementFinder(); + int[] array = {}; + List peaks = finder.findPeakElements(array); + assertEquals(0, peaks.size()); + } + + @Test + void findPeakElement_givenArrayOfIntegers_whenPeaksAtExtremes_thenReturnsCorrectPeak() { + PeakElementFinder finder = new PeakElementFinder(); + int[] array = {5, 2, 1, 3, 4}; + List peaks = finder.findPeakElements(array); + assertEquals(2, peaks.size()); + assertTrue(peaks.contains(5)); + assertTrue(peaks.contains(4)); + } + + @Test + void findPeakElement_givenArrayOfIntegers_whenPlateaus_thenReturnsCorrectPeak() { + PeakElementFinder finder = new PeakElementFinder(); + int[] array = {1, 2, 2, 2, 3, 4, 5}; + List peaks = finder.findPeakElements(array); + assertEquals(1, peaks.size()); + assertTrue(peaks.contains(5)); + } +} diff --git a/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/SinglePeakFinderUnitTest.java b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/SinglePeakFinderUnitTest.java new file mode 100644 index 0000000000..9e4cea2c0e --- /dev/null +++ b/core-java-modules/core-java-collections-array-list-2/src/test/java/com/baeldung/peakelements/SinglePeakFinderUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.peakelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.OptionalInt; + +public class SinglePeakFinderUnitTest { + + @Test + void findSinglePeak_givenArrayOfIntegers_whenValidInput_thenReturnsCorrectPeak() { + int[] arr = {0, 10, 2, 4, 5, 1}; + OptionalInt peak = SinglePeakFinder.findSinglePeak(arr); + assertTrue(peak.isPresent()); + assertEquals(10, peak.getAsInt()); + } + + @Test + void findSinglePeak_givenEmptyArray_thenReturnsEmptyOptional() { + int[] arr = {}; + OptionalInt peak = SinglePeakFinder.findSinglePeak(arr); + assertTrue(peak.isEmpty()); + } + + @Test + void findSinglePeak_givenEqualElementArray_thenReturnsCorrectPeak() { + int[] arr = {-2, -2, -2, -2, -2}; + OptionalInt peak = SinglePeakFinder.findSinglePeak(arr); + assertTrue(peak.isPresent()); + assertEquals(-2, peak.getAsInt()); + } +} diff --git a/core-java-modules/core-java-collections-array-list/pom.xml b/core-java-modules/core-java-collections-array-list/pom.xml index 034b2d820d..384808af07 100644 --- a/core-java-modules/core-java-collections-array-list/pom.xml +++ b/core-java-modules/core-java-collections-array-list/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-array-list - core-java-collections-array-list jar + core-java-collections-array-list com.baeldung.core-java-modules @@ -19,12 +19,6 @@ commons-collections4 ${commons-collections4.version} - - com.google.guava - guava - ${guava.version} - test - diff --git a/core-java-modules/core-java-collections-conversions-2/pom.xml b/core-java-modules/core-java-collections-conversions-2/pom.xml index 7723daa6db..bb88cbebd1 100644 --- a/core-java-modules/core-java-collections-conversions-2/pom.xml +++ b/core-java-modules/core-java-collections-conversions-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-conversions-2 - core-java-collections-conversions-2 jar + core-java-collections-conversions-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-conversions-3/pom.xml b/core-java-modules/core-java-collections-conversions-3/pom.xml index 4813d33713..d55a1aecdf 100644 --- a/core-java-modules/core-java-collections-conversions-3/pom.xml +++ b/core-java-modules/core-java-collections-conversions-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-conversions-3 - core-java-collections-conversions-3 jar + core-java-collections-conversions-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-conversions/pom.xml b/core-java-modules/core-java-collections-conversions/pom.xml index 78e9847c0a..d01eae043f 100644 --- a/core-java-modules/core-java-collections-conversions/pom.xml +++ b/core-java-modules/core-java-collections-conversions/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-conversions - core-java-collections-conversions jar + core-java-collections-conversions com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-list-2/pom.xml b/core-java-modules/core-java-collections-list-2/pom.xml index a305cdffc8..2b3c00601e 100644 --- a/core-java-modules/core-java-collections-list-2/pom.xml +++ b/core-java-modules/core-java-collections-list-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-2 - core-java-collections-list-2 jar + core-java-collections-list-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-list-3/pom.xml b/core-java-modules/core-java-collections-list-3/pom.xml index f01fe1f3b9..8d40210cfd 100644 --- a/core-java-modules/core-java-collections-list-3/pom.xml +++ b/core-java-modules/core-java-collections-list-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-3 - core-java-collections-list-3 jar + core-java-collections-list-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-list-4/pom.xml b/core-java-modules/core-java-collections-list-4/pom.xml index 0f170b0b85..067808d2d1 100644 --- a/core-java-modules/core-java-collections-list-4/pom.xml +++ b/core-java-modules/core-java-collections-list-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-4 - core-java-collections-list-4 jar + core-java-collections-list-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-list-5/pom.xml b/core-java-modules/core-java-collections-list-5/pom.xml index 8fc5062ac0..d370b14858 100644 --- a/core-java-modules/core-java-collections-list-5/pom.xml +++ b/core-java-modules/core-java-collections-list-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-5 - core-java-collections-list-5 jar + core-java-collections-list-5 com.baeldung.core-java-modules @@ -60,6 +60,5 @@ 1.21 2.10.1 - 20230618 \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-6/README.md b/core-java-modules/core-java-collections-list-6/README.md index bf634fb79c..c66a611caf 100644 --- a/core-java-modules/core-java-collections-list-6/README.md +++ b/core-java-modules/core-java-collections-list-6/README.md @@ -4,3 +4,5 @@ - [Call a Method on Each Element of a List in Java](https://www.baeldung.com/java-call-method-each-list-item) - [Sorting One List Based on Another List in Java](https://www.baeldung.com/java-sorting-one-list-using-another) - [Reset ListIterator to First Element of the List in Java](https://www.baeldung.com/java-reset-listiterator) +- [Modify and Print List Items With Java Streams](https://www.baeldung.com/java-stream-list-update-print-elements) +- [Add One Element to an Immutable List in Java](https://www.baeldung.com/java-immutable-list-add-element) diff --git a/core-java-modules/core-java-collections-list-6/pom.xml b/core-java-modules/core-java-collections-list-6/pom.xml index 06e00e8dce..a560417f9e 100644 --- a/core-java-modules/core-java-collections-list-6/pom.xml +++ b/core-java-modules/core-java-collections-list-6/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-6 - core-java-collections-list-6 jar + core-java-collections-list-6 com.baeldung.core-java-modules @@ -14,11 +14,6 @@ - - com.google.guava - guava - ${guava.version} - io.vavr vavr diff --git a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java new file mode 100644 index 0000000000..397aca8906 --- /dev/null +++ b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.addtoimmutablelist; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class AddElementsToImmutableListUnitTest { + + public static List appendAnElement(List immutableList, T element) { + List tmpList = new ArrayList<>(immutableList); + tmpList.add(element); + return Collections.unmodifiableList(tmpList); + } + + @SafeVarargs + public static List appendElements(List immutableList, T... elements) { + List tmpList = new ArrayList<>(immutableList); + tmpList.addAll(Arrays.asList(elements)); + return Collections.unmodifiableList(tmpList); + } + + @Test + void whenCallingAppendAnElement_thenGetExpectedResult() { + List myList = List.of("A", "B", "C", "D", "E"); + List expected = List.of("A", "B", "C", "D", "E", "F"); + List result = appendAnElement(myList, "F"); + assertThat(result).isEqualTo(expected) + .isUnmodifiable(); + } + + @Test + void whenCallingAppendElements_thenGetExpectedResult() { + List myList = List.of("A", "B", "C", "D", "E"); + List expected1 = List.of("A", "B", "C", "D", "E", "F"); + List result1 = appendElements(myList, "F"); + assertThat(result1).isEqualTo(expected1) + .isUnmodifiable(); + + List expected2 = List.of("A", "B", "C", "D", "E", "F", "G", "H", "I"); + List result2 = appendElements(myList, "F", "G", "H", "I"); + assertThat(result2).isEqualTo(expected2) + .isUnmodifiable(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/pom.xml b/core-java-modules/core-java-collections-list/pom.xml index 94abb334e0..1516123c47 100644 --- a/core-java-modules/core-java-collections-list/pom.xml +++ b/core-java-modules/core-java-collections-list/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list - core-java-collections-list jar + core-java-collections-list com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-maps-2/pom.xml b/core-java-modules/core-java-collections-maps-2/pom.xml index 15ca688ad2..c5fd5f637a 100644 --- a/core-java-modules/core-java-collections-maps-2/pom.xml +++ b/core-java-modules/core-java-collections-maps-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps-2 - core-java-collections-maps-2 jar + core-java-collections-maps-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-maps-3/pom.xml b/core-java-modules/core-java-collections-maps-3/pom.xml index 98a0d18fe9..9f67d588ca 100644 --- a/core-java-modules/core-java-collections-maps-3/pom.xml +++ b/core-java-modules/core-java-collections-maps-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps-3 - core-java-collections-maps-3 jar + core-java-collections-maps-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-maps-4/pom.xml b/core-java-modules/core-java-collections-maps-4/pom.xml index 5f7b40fbf6..1ba50187fe 100644 --- a/core-java-modules/core-java-collections-maps-4/pom.xml +++ b/core-java-modules/core-java-collections-maps-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps-4 - core-java-collections-maps-4 jar + core-java-collections-maps-4 com.baeldung.core-java-modules @@ -24,11 +24,6 @@ commons-collections4 ${commons-collections4.version} - - com.google.guava - guava - ${guava.version} - junit junit diff --git a/core-java-modules/core-java-collections-maps-5/pom.xml b/core-java-modules/core-java-collections-maps-5/pom.xml index 593ec5a8f6..11c3e5e3e4 100644 --- a/core-java-modules/core-java-collections-maps-5/pom.xml +++ b/core-java-modules/core-java-collections-maps-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps-5 - core-java-collections-maps-5 jar + core-java-collections-maps-5 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-maps-6/pom.xml b/core-java-modules/core-java-collections-maps-6/pom.xml index 6d10115d31..88c82623d0 100644 --- a/core-java-modules/core-java-collections-maps-6/pom.xml +++ b/core-java-modules/core-java-collections-maps-6/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps-6 - core-java-collections-maps-6 jar + core-java-collections-maps-6 core-java-modules @@ -32,7 +32,7 @@ org.json json - 20230227 + ${org.json.version} junit diff --git a/core-java-modules/core-java-collections-maps-7/README.md b/core-java-modules/core-java-collections-maps-7/README.md index da777d72c3..b8e4454c61 100644 --- a/core-java-modules/core-java-collections-maps-7/README.md +++ b/core-java-modules/core-java-collections-maps-7/README.md @@ -1,6 +1,5 @@ ## Relevant Articles: - [Difference Between putIfAbsent() and computeIfAbsent() in Java’s Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent) -- [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/how-to-write-and-read-a-file-with-a-java-hashmap/) - [How to Write Hashmap to CSV File](https://www.baeldung.com/java-write-hashmap-csv) - [How to Get First or Last Entry From a LinkedHashMap in Java](https://www.baeldung.com/java-linkedhashmap-first-last-key-value-pair) - [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/java-hashmap-write-read-file) diff --git a/core-java-modules/core-java-collections-maps-7/pom.xml b/core-java-modules/core-java-collections-maps-7/pom.xml index b0f0d55c18..186096fe77 100644 --- a/core-java-modules/core-java-collections-maps-7/pom.xml +++ b/core-java-modules/core-java-collections-maps-7/pom.xml @@ -29,11 +29,7 @@ commons-csv ${csv.version} - - com.google.guava - guava - ${guava.version} - + org.openjdk.jmh jmh-core diff --git a/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java b/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java index e23a5da8ff..ace19bb00c 100644 --- a/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java +++ b/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java @@ -1,5 +1,6 @@ package com.baeldung.writehashmaptocsvfile; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import java.io.File; @@ -63,4 +64,16 @@ public class WriteHashmaptoCVSFileUnitTest { // Ensure the CSV file exists assertTrue(new File("employee_data2.csv").exists()); } + + @AfterAll + public static void cleanUp() { + final File employeeData = new File("employee_data.csv"); + if (employeeData.exists()) { + employeeData.deleteOnExit(); + } + final File employeeData2 = new File("employee_data2.csv"); + if (employeeData2.exists()) { + employeeData2.deleteOnExit(); + } + } } diff --git a/core-java-modules/core-java-collections-maps-8/README.md b/core-java-modules/core-java-collections-maps-8/README.md new file mode 100644 index 0000000000..f3dcc6b8bb --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Find Map Keys with Duplicate Values in Java](https://www.baeldung.com/java-map-find-keys-repeated-values) diff --git a/core-java-modules/core-java-collections-maps-8/pom.xml b/core-java-modules/core-java-collections-maps-8/pom.xml new file mode 100644 index 0000000000..8c4454cf0f --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + core-java-collections-maps-8 + core-java-collections-maps-8 + jar + + + core-java-modules + com.baeldung.core-java-modules + 0.0.1-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + diff --git a/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java b/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java new file mode 100644 index 0000000000..a7491fd257 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java @@ -0,0 +1,127 @@ +package com.baeldung.map.valuetokeyset; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toSet; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +public class ConvertMapKeyValueToMapValueKeySetUnitTest { + + private static final Map INPUT_MAP = Map.of( + // @formatter:off + "Kai", "Linux", + "Eric", "MacOS", + "Kevin", "Windows", + "Liam", "MacOS", + "David", "Linux", + "Saajan", "Windows", + "Loredana", "MacOS" + // @formatter:on + ); + + private static final Map> EXPECTED = Map.of( + // @formatter:off + "Linux", Set.of("Kai", "David"), + "Windows", Set.of("Saajan", "Kevin"), + "MacOS", Set.of("Eric", "Liam", "Loredana") + // @formatter:on + ); + + private static final Map INPUT_MAP_WITH_NULLS = new HashMap(INPUT_MAP) {{ + put("Tom", null); + put("Jerry", null); + put(null, null); + }}; + + private static final Map> EXPECTED_WITH_NULLS = new HashMap>(EXPECTED) {{ + put(null, new HashSet() {{ + add("Tom"); + add("Jerry"); + add(null); + }}); + }}; + + public static Map> transformMap(Map input) { + Map> resultMap = new HashMap<>(); + for (Map.Entry entry : input.entrySet()) { + if (!resultMap.containsKey(entry.getValue())) { + resultMap.put(entry.getValue(), new HashSet<>()); + } + resultMap.get(entry.getValue()) + .add(entry.getKey()); + } + return resultMap; + } + + @Test + void whenUsingClassicLoopBasedSolution_thenGetExpectedResult() { + Map> result = transformMap(INPUT_MAP); + assertEquals(EXPECTED, result); + + Map> result2 = transformMap(INPUT_MAP_WITH_NULLS); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingJava8StreamGroupingBy_thenGetExpectedResult() { + Map> result = INPUT_MAP.entrySet() + .stream() + .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet()))); + assertEquals(EXPECTED, result); + + assertThrows(NullPointerException.class, () -> INPUT_MAP_WITH_NULLS.entrySet() + .stream() + .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet())))); + } + + @Test + void whenUsingJava8ForEach_thenGetExpectedResult() { + Map> result = new HashMap<>(); + INPUT_MAP.forEach((key, value) -> result.computeIfAbsent(value, k -> new HashSet<>()) + .add(key)); + assertEquals(EXPECTED, result); + + Map> result2 = new HashMap<>(); + INPUT_MAP_WITH_NULLS.forEach((key, value) -> result2.computeIfAbsent(value, k -> new HashSet<>()) + .add(key)); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingGuavaMultiMapCollector_thenGetExpectedResult() { + Map> result = INPUT_MAP.entrySet() + .stream() + .collect(collectingAndThen(Multimaps.toMultimap(Map.Entry::getValue, Map.Entry::getKey, HashMultimap::create), Multimaps::asMap)); + assertEquals(EXPECTED, result); + + Map> result2 = INPUT_MAP_WITH_NULLS.entrySet() + .stream() + .collect(collectingAndThen(Multimaps.toMultimap(Map.Entry::getValue, Map.Entry::getKey, HashMultimap::create), Multimaps::asMap)); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingGuavaInvertFromAndForMap_thenGetExpectedResult() { + SetMultimap multiMap = Multimaps.invertFrom(Multimaps.forMap(INPUT_MAP), HashMultimap.create()); + Map> result = Multimaps.asMap(multiMap); + assertEquals(EXPECTED, result); + + SetMultimap multiMapWithNulls = Multimaps.invertFrom(Multimaps.forMap(INPUT_MAP_WITH_NULLS), HashMultimap.create()); + Map> result2 = Multimaps.asMap(multiMapWithNulls); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml index 5e19117e08..7f0f617df0 100644 --- a/core-java-modules/core-java-collections-maps/pom.xml +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-maps - core-java-collections-maps jar + core-java-collections-maps com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections-set-2/README.md b/core-java-modules/core-java-collections-set-2/README.md index ee41908faf..1eed623824 100644 --- a/core-java-modules/core-java-collections-set-2/README.md +++ b/core-java-modules/core-java-collections-set-2/README.md @@ -6,4 +6,5 @@ - [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set) - [Cartesian Product of Any Number of Sets in Java](https://www.baeldung.com/java-cartesian-product-sets) - [How to Get Index of an Item in Java Set](https://www.baeldung.com/java-set-element-find-index) +- [Check if an Element Is Present in a Set in Java](https://www.baeldung.com/java-set-membership) - More articles: [[<-- prev]](/core-java-modules/core-java-collections-set) diff --git a/core-java-modules/core-java-collections-set-2/pom.xml b/core-java-modules/core-java-collections-set-2/pom.xml index 894bce86b7..ac4fd7dc73 100644 --- a/core-java-modules/core-java-collections-set-2/pom.xml +++ b/core-java-modules/core-java-collections-set-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-set-2 - core-java-collections-set-2 jar + core-java-collections-set-2 com.baeldung.core-java-modules @@ -32,11 +32,6 @@ 7.7.0 test - - com.google.guava - guava - ${guava.version} - diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java new file mode 100644 index 0000000000..9d3c9a5c0d --- /dev/null +++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java @@ -0,0 +1,71 @@ +package com.baeldung.checkifpresentinset; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.SetUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class CheckIfPresentInSetUnitTest { + + private static final Set CITIES = new HashSet<>(); + + @BeforeAll + static void setup() { + CITIES.add("Paris"); + CITIES.add("London"); + CITIES.add("Tokyo"); + CITIES.add("Tamassint"); + CITIES.add("New york"); + } + + @Test + void givenASet_whenUsingStreamAnyMatchMethod_thenCheck() { + boolean isPresent = CITIES.stream() + .anyMatch(city -> city.equals("London")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingStreamFilterMethod_thenCheck() { + long resultCount = CITIES.stream() + .filter(city -> city.equals("Tamassint")) + .count(); + + assertThat(resultCount).isPositive(); + } + + @Test + void givenASet_whenUsingContainsMethod_thenCheck() { + assertThat(CITIES.contains("London")).isTrue(); + assertThat(CITIES.contains("Madrid")).isFalse(); + } + + @Test + void givenASet_whenUsingCollectionsDisjointMethod_thenCheck() { + boolean isPresent = !Collections.disjoint(CITIES, Collections.singleton("Paris")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingCollectionUtilsContainsAnyMethod_thenCheck() { + boolean isPresent = CollectionUtils.containsAny(CITIES, Collections.singleton("Paris")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingSetUtilsIntersectionMethod_thenCheck() { + Set result = SetUtils.intersection(CITIES, Collections.singleton("Tamassint")); + + assertThat(result).isNotEmpty(); + } + +} diff --git a/core-java-modules/core-java-collections-set/pom.xml b/core-java-modules/core-java-collections-set/pom.xml index b3cd1ec90f..107ff0a22a 100644 --- a/core-java-modules/core-java-collections-set/pom.xml +++ b/core-java-modules/core-java-collections-set/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-set - core-java-collections-set jar + core-java-collections-set com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md index 574f61ac6a..ec274fa051 100644 --- a/core-java-modules/core-java-collections/README.md +++ b/core-java-modules/core-java-collections/README.md @@ -13,4 +13,5 @@ This module contains articles about Java collections - [Guide to the Java Queue Interface](https://www.baeldung.com/java-queue) - [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) - [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list) +- [Adding Elements to a Collection During Iteration](https://www.baeldung.com/java-add-elements-collection) - More articles: [[next -->]](/core-java-modules/core-java-collections-2) diff --git a/core-java-modules/core-java-collections/pom.xml b/core-java-modules/core-java-collections/pom.xml index be91492d06..cb6f946cfd 100644 --- a/core-java-modules/core-java-collections/pom.xml +++ b/core-java-modules/core-java-collections/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections - core-java-collections jar + core-java-collections com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/listiteration/ListIterationUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/listiteration/ListIterationUnitTest.java new file mode 100644 index 0000000000..2f1b2cc083 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/listiteration/ListIterationUnitTest.java @@ -0,0 +1,71 @@ +package com.baeldung.listiteration; + +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertIterableEquals; + +public class ListIterationUnitTest { + + List programmingLanguages = new ArrayList<>(List.of("Java", "Python", "C++")); + List numbers = new ArrayList<>(List.of(1, 2, 3)); + + @Test + public void givenStringList_whenAddElementWithListIterator_thenModifiedList() { + ListIterator listIterator = programmingLanguages.listIterator(); + while (listIterator.hasNext()) { + String language = listIterator.next(); + if (language.equals("Python")) { + listIterator.add("JavaScript"); + } + } + + assertIterableEquals(Arrays.asList("Java", "Python", "JavaScript", "C++"), programmingLanguages); + } + + @Test + public void givenNumericalList_whenMultiplyElementWithListIterator_thenModifiedList() { + ListIterator listIterator = numbers.listIterator(); + while (listIterator.hasNext()) { + int num = listIterator.next(); + if (num == 2) { + listIterator.add(num * 10); + } + } + assertIterableEquals(Arrays.asList(1, 2, 20, 3), numbers); + } + + @Test + public void givenStringList_whenAddElementWithEnhancedForLoopAndCopy_thenModifiedList() { + List copyOfWords = new ArrayList<>(programmingLanguages); + for (String word : copyOfWords) { + programmingLanguages.add(word.toUpperCase()); // Modified: Convert to uppercase + } + assertIterableEquals(Arrays.asList("Java", "Python", "C++", "JAVA", "PYTHON", "C++"), programmingLanguages); + } + + @Test + public void givenNumericalList_whenMultiplyElementWithEnhancedForLoopAndCopy_thenModifiedList() { + List copyOfNumbers = new ArrayList<>(numbers); + for (int num : copyOfNumbers) { + numbers.add(num * 2); + } + assertIterableEquals(Arrays.asList(1, 2, 3, 2, 4, 6), numbers); + } + + @Test + public void givenStringList_whenConvertToUpperCaseWithJava8Stream_thenModifiedList() { + programmingLanguages = programmingLanguages.stream().map(String::toUpperCase).collect(Collectors.toList()); + assertIterableEquals(Arrays.asList("JAVA", "PYTHON", "C++"), programmingLanguages); + } + + @Test + public void givenNumericalList_whenMultiplyByThreeWithJava8Stream_thenModifiedList() { + numbers = numbers.stream().map(num -> num * 3).collect(Collectors.toList()); + assertIterableEquals(Arrays.asList(3, 6, 9), numbers); + } + +} diff --git a/core-java-modules/core-java-compiler/pom.xml b/core-java-modules/core-java-compiler/pom.xml index 8f2be3f142..86afbc1ca8 100644 --- a/core-java-modules/core-java-compiler/pom.xml +++ b/core-java-modules/core-java-compiler/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-compiler 0.1.0-SNAPSHOT - core-java-compiler jar + core-java-compiler com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-2/pom.xml b/core-java-modules/core-java-concurrency-2/pom.xml index e373c829cc..593078a3b0 100644 --- a/core-java-modules/core-java-concurrency-2/pom.xml +++ b/core-java-modules/core-java-concurrency-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-2 - core-java-concurrency-2 jar + core-java-concurrency-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-advanced-2/pom.xml b/core-java-modules/core-java-concurrency-advanced-2/pom.xml index 5c96684311..8d8f259ca6 100644 --- a/core-java-modules/core-java-concurrency-advanced-2/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-advanced-2 - core-java-concurrency-advanced-2 jar + core-java-concurrency-advanced-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-advanced-3/pom.xml b/core-java-modules/core-java-concurrency-advanced-3/pom.xml index e3b399782e..d09b0d55e8 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-advanced-3 - core-java-concurrency-advanced-3 jar + core-java-concurrency-advanced-3 com.baeldung.core-java-modules @@ -86,7 +86,7 @@ 1.8 0.22.6 1.9.20.1 - 0.43 + 0.55.0 1.2.3 0.14.1 1.9.20.1 diff --git a/core-java-modules/core-java-concurrency-advanced-4/pom.xml b/core-java-modules/core-java-concurrency-advanced-4/pom.xml index 2ffe19b13c..e79ecf8cc0 100644 --- a/core-java-modules/core-java-concurrency-advanced-4/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-advanced-4 - core-java-concurrency-advanced-4 jar + core-java-concurrency-advanced-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-advanced-5/README.md b/core-java-modules/core-java-concurrency-advanced-5/README.md index 718b5451dc..45937aa47f 100644 --- a/core-java-modules/core-java-concurrency-advanced-5/README.md +++ b/core-java-modules/core-java-concurrency-advanced-5/README.md @@ -3,3 +3,5 @@ - [Why wait() Requires Synchronization?](https://www.baeldung.com/java-wait-necessary-synchronization) - [Working with Exceptions in Java CompletableFuture](https://www.baeldung.com/java-exceptions-completablefuture) - [CountDownLatch vs. Semaphore](https://www.baeldung.com/java-countdownlatch-vs-semaphore) +- [Callbacks in ListenableFuture and CompletableFuture](https://www.baeldung.com/java-callbacks-listenablefuture-completablefuture) +- [Guide to ExecutorService vs. CompletableFuture](https://www.baeldung.com/java-executorservice-vs-completablefuture) diff --git a/core-java-modules/core-java-concurrency-advanced-5/pom.xml b/core-java-modules/core-java-concurrency-advanced-5/pom.xml index b84d3810bb..9caa943a57 100644 --- a/core-java-modules/core-java-concurrency-advanced-5/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced-5/pom.xml @@ -2,11 +2,10 @@ - 4.0.0 core-java-concurrency-advanced-5 - core-java-concurrency-advanced-5 jar + core-java-concurrency-advanced-5 com.baeldung.core-java-modules @@ -29,8 +28,8 @@ - 1.8 - 1.8 + 9 + 9 \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/CompletableFutureDemo.java b/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/CompletableFutureDemo.java new file mode 100644 index 0000000000..b45156db15 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/CompletableFutureDemo.java @@ -0,0 +1,64 @@ +package com.baeldung.executorservicevscompletablefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.TimeUnit; + +public class CompletableFutureDemo { + + public static void completableFutureMethod() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + return 42; + }); + + System.out.println(future.join()); + } + + public static void chainingTaskExample() { + CompletableFuture firstTask = CompletableFuture.supplyAsync(() -> { + return 42; + }); + + CompletableFuture secondTask = firstTask.thenApply(result -> { + return "Result based on Task 1: " + result; + }); + + System.out.println(secondTask.join()); + } + + public static void exceptionHandlingExample() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + // Simulate a task that might throw an exception + if (true) { + throw new RuntimeException("Something went wrong!"); + } + return "Success"; + }) + .exceptionally(ex -> { + System.err.println("Error in task: " + ex.getMessage()); + // Can optionally return a default value + return "Error occurred"; + }); + + future.thenAccept(result -> System.out.println("Result: " + result)); + } + + public static void timeoutExample() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + System.err.println("Task execution timed out!"); + } + return "Task completed"; + }); + + CompletableFuture timeoutFuture = future.completeOnTimeout("Timed out!", 2, TimeUnit.SECONDS); + String result = timeoutFuture.join(); + System.out.println("Result: " + result); + } + + public static void main(String[] args) { + timeoutExample(); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/ExecutorServiceDemo.java b/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/ExecutorServiceDemo.java new file mode 100644 index 0000000000..99ddea9f2b --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-5/src/main/java/com/baeldung/executorservicevscompletablefuture/ExecutorServiceDemo.java @@ -0,0 +1,98 @@ +package com.baeldung.executorservicevscompletablefuture; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class ExecutorServiceDemo { + + public static void executorServiceMethod() throws ExecutionException, InterruptedException { + ExecutorService executor = Executors.newFixedThreadPool(3); + Future future = executor.submit(() -> { + return 42; + }); + + System.out.println(future.get()); + } + + public static void chainingTaskExample() { + ExecutorService executor = Executors.newFixedThreadPool(2); + Future firstTask = executor.submit(() -> {return 42;}); + + Future secondTask = executor.submit(() -> { + try { + Integer result = firstTask.get(); + return "Result based on Task 1: " + result; + } catch (InterruptedException | ExecutionException e) { + // Handle exception + System.err.println("Error occured: " + e.getMessage()); + } + return null; + }); + executor.shutdown(); + + try { + // Wait for the second task to complete and retrieve the result + String result = secondTask.get(); + System.out.println(result); // Output: Result based on Task 1: 42 + } catch (InterruptedException | ExecutionException e) { + // Handle exception + System.err.println("Error occured: " + e.getMessage()); + } + } + + public static void exceptionHandlingExample() { + ExecutorService executor = Executors.newFixedThreadPool(2); + Future future = executor.submit(() -> { + // Simulate a task that might throw an exception + if (true) { + throw new RuntimeException("Something went wrong!"); + } + return "Success"; + }); + + try { + // This might block the main thread if the task throws an exception + String result = future.get(); + System.out.println("Result: " + result); + } catch (InterruptedException | ExecutionException e) { + // Handle exceptions thrown by the task or during retrieval + System.err.println("Error occured: " + e.getMessage()); + } finally { + executor.shutdown(); + } + } + + public static void timeoutExample() { + ExecutorService executor = Executors.newFixedThreadPool(2); + Future future = executor.submit(() -> { + try { + System.out.println("Start"); + Thread.sleep(5000); + System.out.println("End"); + } catch (InterruptedException e) { + System.err.println("Error occured: " + e.getMessage()); + } + return "Task completed"; + }); + + try { + String result = future.get(2, TimeUnit.SECONDS); + System.out.println("Result: " + result); + } catch (TimeoutException e) { + System.err.println("Task execution timed out!"); + future.cancel(true); + } catch (Exception e) { + System.err.println("Error occured: " + e.getMessage()); + } finally { + executor.shutdown(); + } + } + + public static void main(String[] args) throws ExecutionException, InterruptedException { + timeoutExample(); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced/pom.xml b/core-java-modules/core-java-concurrency-advanced/pom.xml index 18cfc5371c..5a52bfe1fa 100644 --- a/core-java-modules/core-java-concurrency-advanced/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-advanced - core-java-concurrency-advanced jar + core-java-concurrency-advanced com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-basic-2/pom.xml b/core-java-modules/core-java-concurrency-basic-2/pom.xml index 0cdfd68f03..524a944bcb 100644 --- a/core-java-modules/core-java-concurrency-basic-2/pom.xml +++ b/core-java-modules/core-java-concurrency-basic-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-basic-2 - core-java-concurrency-basic-2 jar + core-java-concurrency-basic-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-basic-3/pom.xml b/core-java-modules/core-java-concurrency-basic-3/pom.xml index 1983d3c163..30b601e083 100644 --- a/core-java-modules/core-java-concurrency-basic-3/pom.xml +++ b/core-java-modules/core-java-concurrency-basic-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-basic-3 - core-java-concurrency-basic-3 jar + core-java-concurrency-basic-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-basic/pom.xml b/core-java-modules/core-java-concurrency-basic/pom.xml index 6121cddc39..26bb64429d 100644 --- a/core-java-modules/core-java-concurrency-basic/pom.xml +++ b/core-java-modules/core-java-concurrency-basic/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-basic - core-java-concurrency-basic jar + core-java-concurrency-basic com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-collections-2/pom.xml b/core-java-modules/core-java-concurrency-collections-2/pom.xml index a85721e474..8f5f2f79ff 100644 --- a/core-java-modules/core-java-concurrency-collections-2/pom.xml +++ b/core-java-modules/core-java-concurrency-collections-2/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-collections-2 - core-java-concurrency-collections-2 jar + core-java-concurrency-collections-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-collections/pom.xml b/core-java-modules/core-java-concurrency-collections/pom.xml index a35da4ce49..6b24be095e 100644 --- a/core-java-modules/core-java-concurrency-collections/pom.xml +++ b/core-java-modules/core-java-concurrency-collections/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-collections - core-java-concurrency-collections jar + core-java-concurrency-collections com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-concurrency-simple/pom.xml b/core-java-modules/core-java-concurrency-simple/pom.xml index eb196027aa..b36e16a667 100644 --- a/core-java-modules/core-java-concurrency-simple/pom.xml +++ b/core-java-modules/core-java-concurrency-simple/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-concurrency-simple - core-java-concurrency-simple jar + core-java-concurrency-simple com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-conditionals/pom.xml b/core-java-modules/core-java-conditionals/pom.xml index f2ad7df749..08ca6db2f7 100644 --- a/core-java-modules/core-java-conditionals/pom.xml +++ b/core-java-modules/core-java-conditionals/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-conditionals 0.1.0-SNAPSHOT - core-java-conditionals jar + core-java-conditionals com.baeldung diff --git a/core-java-modules/core-java-console/pom.xml b/core-java-modules/core-java-console/pom.xml index a761b2749e..e18f85e2d1 100644 --- a/core-java-modules/core-java-console/pom.xml +++ b/core-java-modules/core-java-console/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-console - core-java-console jar + core-java-console com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-date-operations-1/pom.xml b/core-java-modules/core-java-date-operations-1/pom.xml index 45a885db5e..1a824790b8 100644 --- a/core-java-modules/core-java-date-operations-1/pom.xml +++ b/core-java-modules/core-java-date-operations-1/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-date-operations-1 - core-java-date-operations-1 jar + core-java-date-operations-1 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-date-operations-2/pom.xml b/core-java-modules/core-java-date-operations-2/pom.xml index 86fbbf614e..cadc0e23fc 100644 --- a/core-java-modules/core-java-date-operations-2/pom.xml +++ b/core-java-modules/core-java-date-operations-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-date-operations-2 - core-java-date-operations-2 jar + core-java-date-operations-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-date-operations-3/pom.xml b/core-java-modules/core-java-date-operations-3/pom.xml index 8e4740785c..f0f1323c54 100644 --- a/core-java-modules/core-java-date-operations-3/pom.xml +++ b/core-java-modules/core-java-date-operations-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-date-operations-3 - core-java-date-operations-3 jar + core-java-date-operations-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-date-operations-4/README.md b/core-java-modules/core-java-date-operations-4/README.md index 0e9bc710c8..97d738f2ba 100644 --- a/core-java-modules/core-java-date-operations-4/README.md +++ b/core-java-modules/core-java-date-operations-4/README.md @@ -5,3 +5,4 @@ This module contains articles about date operations in Java. - [Calculate Number of Weekdays Between Two Dates in Java](https://www.baeldung.com/java-count-weekdays-between-two-dates) - [Convert Long to Date in Java](https://www.baeldung.com/java-long-date-conversion) - [Convert Date to Unix Timestamp in Java](https://www.baeldung.com/java-convert-date-unix-timestamp) +- [Checking if a Date Object Equals Yesterday](https://www.baeldung.com/java-date-check-yesterday) diff --git a/core-java-modules/core-java-date-operations-4/pom.xml b/core-java-modules/core-java-date-operations-4/pom.xml index 317b2cb6e7..934a7ebb5f 100644 --- a/core-java-modules/core-java-date-operations-4/pom.xml +++ b/core-java-modules/core-java-date-operations-4/pom.xml @@ -4,8 +4,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-date-operations-4 + jar core-java-date-operations-4 + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + + @@ -18,13 +25,6 @@ - jar - - - com.baeldung.core-java-modules - core-java-modules - 0.0.1-SNAPSHOT - diff --git a/core-java-modules/core-java-date-operations-4/src/test/java/com/baeldung/compareyesterday/CompareYesterdayUnitTest.java b/core-java-modules/core-java-date-operations-4/src/test/java/com/baeldung/compareyesterday/CompareYesterdayUnitTest.java new file mode 100644 index 0000000000..75f63317a7 --- /dev/null +++ b/core-java-modules/core-java-date-operations-4/src/test/java/com/baeldung/compareyesterday/CompareYesterdayUnitTest.java @@ -0,0 +1,116 @@ +package com.baeldung.compareyesterday; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.Calendar; +import java.util.Date; + +import org.joda.time.DateTime; +import org.junit.jupiter.api.Test; + +public class CompareYesterdayUnitTest { + + @Test + void givenYesterdayDate_whenCompareWithCalendar_returnTrue() { + // To simulate yesterday + Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24)); + Calendar expectedCalendar = Calendar.getInstance(); + expectedCalendar.setTime(date); + + Calendar actualCalendar = Calendar.getInstance(); + actualCalendar.add(Calendar.DATE, -1); + + boolean isEqualToYesterday = expectedCalendar.get(Calendar.YEAR) == actualCalendar.get(Calendar.YEAR) && + expectedCalendar.get(Calendar.MONTH) == actualCalendar.get(Calendar.MONTH) && + expectedCalendar.get(Calendar.DAY_OF_MONTH) == actualCalendar.get(Calendar.DAY_OF_MONTH); + assertTrue(isEqualToYesterday); + } + + @Test + void givenTodayDate_whenCompareWithCalendar_returnFalse() { + Calendar expectedCalendar = Calendar.getInstance(); + + Calendar actualCalendar = Calendar.getInstance(); + actualCalendar.add(Calendar.DATE, -1); + + boolean isEqualToYesterday = expectedCalendar.get(Calendar.YEAR) == actualCalendar.get(Calendar.YEAR) && + expectedCalendar.get(Calendar.MONTH) == actualCalendar.get(Calendar.MONTH) && + expectedCalendar.get(Calendar.DAY_OF_MONTH) == actualCalendar.get(Calendar.DAY_OF_MONTH); + assertFalse(isEqualToYesterday); + } + + @Test + void givenYesterdayDate_whenCompareWithDateMilliseconds_returnTrue() { + // Create a Date object representing yesterday + Date expectedDate = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24)); + long yesterdayMidnightMillis = Instant.now() + .minus(1, ChronoUnit.DAYS) + .toEpochMilli(); + + boolean isEqualToYesterday = expectedDate.getTime() >= yesterdayMidnightMillis && expectedDate.getTime() < yesterdayMidnightMillis + 86_400_000; + assertTrue(isEqualToYesterday); + } + + @Test + void givenTodayDate_whenCompareWithDateMilliseconds_returnFalse() { + // Create a Date object representing yesterday + Date expectedDate = new Date(); + long yesterdayMidnightMillis = Instant.now() + .minus(1, ChronoUnit.DAYS) + .toEpochMilli(); + + boolean isEqualToYesterday = expectedDate.getTime() >= yesterdayMidnightMillis && expectedDate.getTime() < yesterdayMidnightMillis + 86_400_000; + assertFalse(isEqualToYesterday); + } + + @Test + void givenYesterdayDate_whenCompareWithLocalDate_returnTrue() { + // To simulate yesterday + Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24)); + LocalDate expectedLocalDate = LocalDate.of(date.getYear() + 1900, date.getMonth() + 1, date.getDate()); + + LocalDate actualLocalDate = LocalDate.now() + .minusDays(1); + boolean isEqualToYesterday = expectedLocalDate.equals(actualLocalDate); + assertTrue(isEqualToYesterday); + } + + @Test + void givenTodayDate_whenCompareWithLocalDate_returnFalse() { + LocalDate expectedLocalDate = LocalDate.now(); + LocalDate actualLocalDate = LocalDate.now() + .minusDays(1); + boolean isEqualToYesterday = expectedLocalDate.equals(actualLocalDate); + assertFalse(isEqualToYesterday); + } + + @Test + void givenYesterdayDate_whenCompareWithJodaTime_returnTrue() { + // To simulate yesterday + Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24)); + DateTime expectedDateTime = new DateTime(date).withTimeAtStartOfDay(); + + DateTime actualDateTime = DateTime.now() + .minusDays(1) + .withTimeAtStartOfDay(); + + boolean isEqualToYesterday = expectedDateTime.equals(actualDateTime); + assertTrue(isEqualToYesterday); + } + + @Test + void givenTodayDate_whenCompareWithJodaTime_returnFalse() { + DateTime expectedDateTime = DateTime.now() + .withTimeAtStartOfDay(); + DateTime actualDateTime = DateTime.now() + .minusDays(1) + .withTimeAtStartOfDay(); + + boolean isEqualToYesterday = expectedDateTime.equals(actualDateTime); + assertFalse(isEqualToYesterday); + } +} diff --git a/core-java-modules/core-java-datetime-conversion-2/README.md b/core-java-modules/core-java-datetime-conversion-2/README.md index 7fe174b385..1a2d1b300b 100644 --- a/core-java-modules/core-java-datetime-conversion-2/README.md +++ b/core-java-modules/core-java-datetime-conversion-2/README.md @@ -5,3 +5,4 @@ This module contains articles about converting between Java date and time object ### Relevant Articles: - [Convert Gregorian to Hijri Date in Java](https://www.baeldung.com/java-date-gregorian-hijri-conversion) - [Convert String Date to XMLGregorianCalendar in Java](https://www.baeldung.com/java-string-date-xmlgregoriancalendar-conversion) +- [Convert TemporalAccessor to LocalDate](https://www.baeldung.com/java-temporalaccessor-localdate-conversion) diff --git a/core-java-modules/core-java-datetime-conversion-2/pom.xml b/core-java-modules/core-java-datetime-conversion-2/pom.xml index 13849bc563..74819926d8 100644 --- a/core-java-modules/core-java-datetime-conversion-2/pom.xml +++ b/core-java-modules/core-java-datetime-conversion-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-datetime-conversion-2 - core-java-datetime-conversion-2 jar + core-java-datetime-conversion-2 com.baeldung.core-java-modules @@ -29,7 +29,6 @@ ummalqura-calendar ${ummalqura-calendar.version} - diff --git a/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java new file mode 100644 index 0000000000..a634fe2a47 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.TemporalAccessorToLocalDate; + +import org.junit.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; + +import static org.junit.Assert.assertEquals; + +public class TemporalAccessorToLocalDateUnitTest { + String dateString = "2022-03-28"; + TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_LOCAL_DATE.parse(dateString); + + @Test + public void givenTemporalAccessor_whenUsingLocalDateFrom_thenConvertToLocalDate() { + LocalDate convertedDate = LocalDate.from(temporalAccessor); + assertEquals(LocalDate.of(2022, 3, 28), convertedDate); + } + + @Test + public void givenTemporalAccessor_whenUsingTemporalQueries_thenConvertToLocalDate() { + int year = temporalAccessor.query(TemporalQueries.localDate()).getYear(); + int month = temporalAccessor.query(TemporalQueries.localDate()).getMonthValue(); + int day = temporalAccessor.query(TemporalQueries.localDate()).getDayOfMonth(); + + LocalDate convertedDate = LocalDate.of(year, month, day); + assertEquals(LocalDate.of(2022, 3, 28), convertedDate); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-datetime-conversion/pom.xml b/core-java-modules/core-java-datetime-conversion/pom.xml index 52ad29db5c..b0a9812d2a 100644 --- a/core-java-modules/core-java-datetime-conversion/pom.xml +++ b/core-java-modules/core-java-datetime-conversion/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-datetime-conversion - core-java-datetime-conversion jar + core-java-datetime-conversion com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-datetime-string-2/pom.xml b/core-java-modules/core-java-datetime-string-2/pom.xml index d37d4d69a4..c4210c8514 100644 --- a/core-java-modules/core-java-datetime-string-2/pom.xml +++ b/core-java-modules/core-java-datetime-string-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-datetime-string-2 - core-java-datetime-string-2 jar + core-java-datetime-string-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-datetime-string/pom.xml b/core-java-modules/core-java-datetime-string/pom.xml index 41c308aa6c..2bf5761907 100644 --- a/core-java-modules/core-java-datetime-string/pom.xml +++ b/core-java-modules/core-java-datetime-string/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-datetime-string - core-java-datetime-string jar + core-java-datetime-string com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-documentation/pom.xml b/core-java-modules/core-java-documentation/pom.xml index 23443dd5ea..da6f832fb1 100644 --- a/core-java-modules/core-java-documentation/pom.xml +++ b/core-java-modules/core-java-documentation/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-documentation 0.1.0-SNAPSHOT - core-java-documentation jar + core-java-documentation com.baeldung.core-java-modules @@ -14,9 +14,6 @@ 0.0.1-SNAPSHOT - - - diff --git a/core-java-modules/core-java-exceptions-2/pom.xml b/core-java-modules/core-java-exceptions-2/pom.xml index 8bf5605f09..bcb88446a5 100644 --- a/core-java-modules/core-java-exceptions-2/pom.xml +++ b/core-java-modules/core-java-exceptions-2/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-exceptions-2 - core-java-exceptions-2 jar + core-java-exceptions-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-exceptions-3/pom.xml b/core-java-modules/core-java-exceptions-3/pom.xml index 6ef979b54a..4ffe66f075 100644 --- a/core-java-modules/core-java-exceptions-3/pom.xml +++ b/core-java-modules/core-java-exceptions-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-exceptions-3 - core-java-exceptions-3 jar + core-java-exceptions-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-exceptions-4/pom.xml b/core-java-modules/core-java-exceptions-4/pom.xml index c41c782fcc..c57a87c107 100644 --- a/core-java-modules/core-java-exceptions-4/pom.xml +++ b/core-java-modules/core-java-exceptions-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-exceptions-4 - core-java-exceptions-4 jar + core-java-exceptions-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml index 0bb6e86c76..111032c4b4 100644 --- a/core-java-modules/core-java-exceptions/pom.xml +++ b/core-java-modules/core-java-exceptions/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-exceptions - core-java-exceptions jar + core-java-exceptions com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-function/pom.xml b/core-java-modules/core-java-function/pom.xml index 4110b8f6d9..3da113da6a 100644 --- a/core-java-modules/core-java-function/pom.xml +++ b/core-java-modules/core-java-function/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-function - core-java-function jar + core-java-function com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-functional/pom.xml b/core-java-modules/core-java-functional/pom.xml index 3b21dd6e8a..ae912cee1f 100644 --- a/core-java-modules/core-java-functional/pom.xml +++ b/core-java-modules/core-java-functional/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-functional - core-java-functional jar + core-java-functional com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-hex/pom.xml b/core-java-modules/core-java-hex/pom.xml index 71e6b15b2e..3b45bdd85f 100644 --- a/core-java-modules/core-java-hex/pom.xml +++ b/core-java-modules/core-java-hex/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-hex - core-java-hex jar + core-java-hex com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-httpclient/pom.xml b/core-java-modules/core-java-httpclient/pom.xml index 593e73b5cb..a14a394908 100644 --- a/core-java-modules/core-java-httpclient/pom.xml +++ b/core-java-modules/core-java-httpclient/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-httpclient - core-java-httpclient jar + core-java-httpclient com.baeldung diff --git a/core-java-modules/core-java-io-2/pom.xml b/core-java-modules/core-java-io-2/pom.xml index 2892bb4a2e..0287d083b4 100644 --- a/core-java-modules/core-java-io-2/pom.xml +++ b/core-java-modules/core-java-io-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-2 - core-java-io-2 jar + core-java-io-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-io-3/pom.xml b/core-java-modules/core-java-io-3/pom.xml index d9e095ced2..f5e603bd32 100644 --- a/core-java-modules/core-java-io-3/pom.xml +++ b/core-java-modules/core-java-io-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-3 - core-java-io-3 jar + core-java-io-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-io-4/pom.xml b/core-java-modules/core-java-io-4/pom.xml index 78511b68bb..e2534ac714 100644 --- a/core-java-modules/core-java-io-4/pom.xml +++ b/core-java-modules/core-java-io-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-4 - core-java-io-4 jar + core-java-io-4 com.baeldung.core-java-modules @@ -25,11 +25,6 @@ commons-codec ${commons-codec.version} - - com.google.guava - guava - ${guava.version} - diff --git a/core-java-modules/core-java-io-5/README.md b/core-java-modules/core-java-io-5/README.md index ef7ea2d980..d596a7a3a7 100644 --- a/core-java-modules/core-java-io-5/README.md +++ b/core-java-modules/core-java-io-5/README.md @@ -9,5 +9,7 @@ This module contains articles about core Java input and output (IO) - [How to Write Strings to OutputStream in Java](https://www.baeldung.com/java-write-string-outputstream) - [Read a File and Split It Into Multiple Files in Java](https://www.baeldung.com/java-read-file-split-into-several) - [Read and Write Files in Java Using Separate Threads](https://www.baeldung.com/java-read-write-files-different-threads) +- [Convert an OutputStream to a Byte Array in Java](https://www.baeldung.com/java-outputstream-byte-array) +- [Reading a .gz File Line by Line Using GZIPInputStream](https://www.baeldung.com/java-gzipinputstream-read-gz-file-line-by-line) - [[<-- Prev]](/core-java-modules/core-java-io-4) diff --git a/core-java-modules/core-java-io-5/pom.xml b/core-java-modules/core-java-io-5/pom.xml index 5c987a82e1..33a522c642 100644 --- a/core-java-modules/core-java-io-5/pom.xml +++ b/core-java-modules/core-java-io-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-5 - core-java-io-5 jar + core-java-io-5 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java b/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java new file mode 100644 index 0000000000..7065352be7 --- /dev/null +++ b/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java @@ -0,0 +1,73 @@ +package com.baeldung.usinggzipInputstream; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.zip.GZIPInputStream; + +import static java.util.stream.Collectors.toList; + +public class Main { + static String filePath = Objects.requireNonNull(Main.class.getClassLoader().getResource("myFile.gz")).getFile(); + + public static void main(String[] args) throws IOException { + // Test readGZipFile method + List fileContents = readGZipFile(filePath); + System.out.println("Contents of GZIP file:"); + fileContents.forEach(System.out::println); + + // Test findInZipFile method + String searchTerm = "Line 1 content"; + List foundLines = findInZipFile(filePath, searchTerm); + System.out.println("Lines containing '" + searchTerm + "' in GZIP file:"); + foundLines.forEach(System.out::println); + + + // Test useContentsOfZipFile method + System.out.println("Using contents of GZIP file with consumer:"); + useContentsOfZipFile(filePath, linesStream -> { + linesStream.filter(line -> line.length() > 10).forEach(System.out::println); + }); + } + + + public static List readGZipFile(String filePath) throws IOException { + List lines = new ArrayList<>(); + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + String line; + while ((line = bufferedReader.readLine()) != null) { + lines.add(line); + } + } + + return lines; + } + + public static List findInZipFile(String filePath, String toFind) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + return bufferedReader.lines().filter(line -> line.contains(toFind)).collect(toList()); + } + } + + public static void useContentsOfZipFile(String filePath, Consumer> consumer) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + consumer.accept(bufferedReader.lines()); + } + } + +} diff --git a/core-java-modules/core-java-io-5/src/main/resources/myFile.gz b/core-java-modules/core-java-io-5/src/main/resources/myFile.gz new file mode 100644 index 0000000000..47c3ad1e1b Binary files /dev/null and b/core-java-modules/core-java-io-5/src/main/resources/myFile.gz differ diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java new file mode 100644 index 0000000000..efa58f565b --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.openhtmlfiles; + +import org.junit.Test; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.junit.Assert.*; + +public class OpenHtmlFilesUnitTest { + public URL url; + public String absolutePath; + + public OpenHtmlFilesUnitTest() throws URISyntaxException { + url = getClass().getResource("/test.html"); + assert url != null; + File file = new File(url.toURI()); + if (!file.exists()) { + fail(); + } + absolutePath = file.getAbsolutePath(); + } + /* + @Test + public void givenHtmlFile_whenUsingDesktopClass_thenOpenFileInDefaultBrowser() throws IOException { + File htmlFile = new File(absolutePath); + Desktop.getDesktop().browse(htmlFile.toURI()); + assertTrue(true); + } + */ + @Test + public void givenHtmlFile_whenUsingProcessBuilder_thenOpenFileInDefaultBrowser() throws IOException { + ProcessBuilder pb; + if (System.getProperty("os.name").toLowerCase().contains("win")) { + pb = new ProcessBuilder("cmd.exe", "/c", "start", absolutePath); + } else { + pb = new ProcessBuilder("xdg-open", absolutePath); + } + pb.start(); + assertTrue(true); + } +} diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java new file mode 100644 index 0000000000..51814f4581 --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.usinggzipInputstream; + +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class ReadingGZIPUsingGZIPInputStreamUnitTest { + String testFilePath = Objects.requireNonNull(ReadingGZIPUsingGZIPInputStreamUnitTest.class.getClassLoader().getResource("myFile.gz")).getFile(); + List expectedFilteredLines = Arrays.asList("Line 1 content", "Line 2 content", "Line 3 content"); + + @Test + void givenGZFile_whenUsingGZIPInputStream_thenReadLines() throws IOException { + try (Stream lines = Main.readGZipFile(testFilePath).stream()) { + List result = lines + .filter(expectedFilteredLines::contains) + .collect(Collectors.toList()); + + assertEquals(expectedFilteredLines, result); + } + } + + @Test + void givenGZFile_whenUsingtestFindInZipFile_thenReadLines() throws IOException { + String toFind = "Line 1 content"; + + List result = Main.findInZipFile(testFilePath, toFind); + + assertEquals("Line 1 content", result.get(0)); + + } + + @Test + void givenGZFile_whenUsingContentsOfZipFile_thenReadLines() throws IOException { + AtomicInteger count = new AtomicInteger(0); + + Main.useContentsOfZipFile(testFilePath, linesStream -> { + linesStream.filter(line -> line.length() > 10).forEach(line -> count.incrementAndGet()); + }); + + assertEquals(3, count.get()); + } +} diff --git a/core-java-modules/core-java-io-5/src/test/resources/myFile.gz b/core-java-modules/core-java-io-5/src/test/resources/myFile.gz new file mode 100644 index 0000000000..47c3ad1e1b Binary files /dev/null and b/core-java-modules/core-java-io-5/src/test/resources/myFile.gz differ diff --git a/core-java-modules/core-java-io-5/src/test/resources/test.html b/core-java-modules/core-java-io-5/src/test/resources/test.html new file mode 100644 index 0000000000..5cb2c410eb --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/resources/test.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + +

Hello dear friend

+ + \ No newline at end of file diff --git a/core-java-modules/core-java-io-apis-2/README.md b/core-java-modules/core-java-io-apis-2/README.md index 29666826a8..2b08736a11 100644 --- a/core-java-modules/core-java-io-apis-2/README.md +++ b/core-java-modules/core-java-io-apis-2/README.md @@ -11,3 +11,4 @@ This module contains articles about core Java input/output(IO) APIs. - [PrintWriter vs. FileWriter in Java](https://www.baeldung.com/java-printwriter-filewriter-difference) - [Read Input Character-by-Character in Java](https://www.baeldung.com/java-read-input-character) - [Difference Between flush() and close() in Java FileWriter](https://www.baeldung.com/java-filewriter-flush-vs-close) +- [Get a Path to a Resource in a Java JAR File](https://www.baeldung.com/java-get-path-resource-jar) diff --git a/core-java-modules/core-java-io-apis-2/pom.xml b/core-java-modules/core-java-io-apis-2/pom.xml index 89ab6d163a..410c164496 100644 --- a/core-java-modules/core-java-io-apis-2/pom.xml +++ b/core-java-modules/core-java-io-apis-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-apis-2 - core-java-io-apis-2 jar + core-java-io-apis-2 com.baeldung.core-java-modules @@ -96,4 +96,5 @@ 5.9.3 - \ No newline at end of file + + diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java new file mode 100644 index 0000000000..27b3e1535d --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.getpathtoresource; + +import org.junit.Test; + +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + +import static org.junit.Assert.assertNotNull; + +public class GetPathToResourceUnitTest { + + @Test + public void givenFile_whenClassUsed_thenGetResourcePath() { + URL resourceUrl = GetPathToResourceUnitTest.class.getResource("/sampleText1.txt"); + assertNotNull(resourceUrl); + } + + @Test + public void givenFile_whenClassLoaderUsed_thenGetResourcePath() { + URL resourceUrl = GetPathToResourceUnitTest.class.getClassLoader().getResource("sampleText1.txt"); + assertNotNull(resourceUrl); + } + + @Test + public void givenFile_whenPathUsed_thenGetResourcePath() throws Exception { + Path resourcePath = Paths.get(Objects.requireNonNull(GetPathToResourceUnitTest.class.getResource("/sampleText1.txt")).toURI()); + assertNotNull(resourcePath); + } + +} diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java new file mode 100644 index 0000000000..d67b56e10b --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.inputstreamreader; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class InputStreamReaderUnitTest { + @Test + public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + String sampleTxt = "Good day. This is just a test. Good bye."; + Path sampleOut = tempDir.resolve("sample-out.txt"); + List lines = Arrays.asList(sampleTxt); + Files.write(sampleOut, lines); + String absolutePath = String.valueOf(sampleOut.toAbsolutePath()); + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8)) { + boolean isMatched = false; + int b; + StringBuilder sb = new StringBuilder(); + while ((b = reader.read()) != -1) { + sb.append((char) b); + if (sb.toString().contains(sampleTxt)) { + isMatched = true; + break; + } + } + assertThat(isMatched).isTrue(); + } + } +} diff --git a/core-java-modules/core-java-io-apis/README.md b/core-java-modules/core-java-io-apis/README.md index faf7067f74..ee8547f0c5 100644 --- a/core-java-modules/core-java-io-apis/README.md +++ b/core-java-modules/core-java-io-apis/README.md @@ -13,3 +13,4 @@ This module contains articles about core Java input/output(IO) APIs. - [Difference Between FileReader and BufferedReader in Java](https://www.baeldung.com/java-filereader-vs-bufferedreader) - [Read Multiple Inputs on the Same Line in Java](https://www.baeldung.com/java-read-multiple-inputs-same-line) - [Write Console Output to Text File in Java](https://www.baeldung.com/java-write-console-output-file) +- [Java InputStream vs. InputStreamReader](https://www.baeldung.com/java-inputstream-vs-inputstreamreader) diff --git a/core-java-modules/core-java-io-apis/pom.xml b/core-java-modules/core-java-io-apis/pom.xml index 688db146da..10ae4dc41d 100644 --- a/core-java-modules/core-java-io-apis/pom.xml +++ b/core-java-modules/core-java-io-apis/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-apis - core-java-io-apis jar + core-java-io-apis com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-io-conversions-2/pom.xml b/core-java-modules/core-java-io-conversions-2/pom.xml index 9be165eaff..a7087672d2 100644 --- a/core-java-modules/core-java-io-conversions-2/pom.xml +++ b/core-java-modules/core-java-io-conversions-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-conversions-2 - core-java-io-conversions-2 jar + core-java-io-conversions-2 com.baeldung.core-java-modules @@ -22,7 +22,7 @@ org.json json - ${json.version} + ${org.json.version} com.opencsv @@ -55,7 +55,6 @@ 11 11 - 20200518 5.8 diff --git a/core-java-modules/core-java-io-conversions/pom.xml b/core-java-modules/core-java-io-conversions/pom.xml index a44c352df2..002c282ea3 100644 --- a/core-java-modules/core-java-io-conversions/pom.xml +++ b/core-java-modules/core-java-io-conversions/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io-conversions - core-java-io-conversions jar + core-java-io-conversions com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml index 93c9289fdd..4aa4c71e3a 100644 --- a/core-java-modules/core-java-io/pom.xml +++ b/core-java-modules/core-java-io/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-io - core-java-io jar + core-java-io com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-ipc/pom.xml b/core-java-modules/core-java-ipc/pom.xml index b7b37afb1d..a48970bd80 100644 --- a/core-java-modules/core-java-ipc/pom.xml +++ b/core-java-modules/core-java-ipc/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-ipc - core-java-ipc jar + core-java-ipc com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-jar/pom.xml b/core-java-modules/core-java-jar/pom.xml index b3376a503d..460adf45e7 100644 --- a/core-java-modules/core-java-jar/pom.xml +++ b/core-java-modules/core-java-jar/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-jar - core-java-jar jar + core-java-jar com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-jpms/pom.xml b/core-java-modules/core-java-jpms/pom.xml index 3cfa0e3f45..88b912ca55 100644 --- a/core-java-modules/core-java-jpms/pom.xml +++ b/core-java-modules/core-java-jpms/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-jpms - core-java-jpms pom + core-java-jpms com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-jvm-2/pom.xml b/core-java-modules/core-java-jvm-2/pom.xml index a2e553eacf..7ee6891d8d 100644 --- a/core-java-modules/core-java-jvm-2/pom.xml +++ b/core-java-modules/core-java-jvm-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-jvm-2 - core-java-jvm-2 jar + core-java-jvm-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-jvm-3/pom.xml b/core-java-modules/core-java-jvm-3/pom.xml index 78f4201c94..1e09403960 100644 --- a/core-java-modules/core-java-jvm-3/pom.xml +++ b/core-java-modules/core-java-jvm-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-jvm-3 - core-java-jvm-3 jar + core-java-jvm-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-jvm/pom.xml b/core-java-modules/core-java-jvm/pom.xml index 97d8f49be5..be93be5909 100644 --- a/core-java-modules/core-java-jvm/pom.xml +++ b/core-java-modules/core-java-jvm/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-jvm - core-java-jvm jar + core-java-jvm com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lambdas/pom.xml b/core-java-modules/core-java-lambdas/pom.xml index a7fc5355d7..b95308ba1b 100644 --- a/core-java-modules/core-java-lambdas/pom.xml +++ b/core-java-modules/core-java-lambdas/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lambdas - core-java-lambdas jar + core-java-lambdas com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-2/pom.xml b/core-java-modules/core-java-lang-2/pom.xml index 22055cf252..b85c8ce75a 100644 --- a/core-java-modules/core-java-lang-2/pom.xml +++ b/core-java-modules/core-java-lang-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-2 - core-java-lang-2 jar + core-java-lang-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-3/pom.xml b/core-java-modules/core-java-lang-3/pom.xml index f29fa6494a..4771b99f4b 100644 --- a/core-java-modules/core-java-lang-3/pom.xml +++ b/core-java-modules/core-java-lang-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-3 - core-java-lang-3 jar + core-java-lang-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-4/pom.xml b/core-java-modules/core-java-lang-4/pom.xml index 6977621a0e..900cfbe903 100644 --- a/core-java-modules/core-java-lang-4/pom.xml +++ b/core-java-modules/core-java-lang-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-4 - core-java-lang-4 jar + core-java-lang-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-5/pom.xml b/core-java-modules/core-java-lang-5/pom.xml index b65f061fc7..de06a67b3c 100644 --- a/core-java-modules/core-java-lang-5/pom.xml +++ b/core-java-modules/core-java-lang-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-5 - core-java-lang-5 jar + core-java-lang-5 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-math-4/README.md b/core-java-modules/core-java-lang-math-4/README.md new file mode 100644 index 0000000000..377c51848d --- /dev/null +++ b/core-java-modules/core-java-lang-math-4/README.md @@ -0,0 +1,4 @@ +========= + +### Relevant articles: +- [Calculate Percentiles in Java](https://www.baeldung.com/java-compute-percentiles) diff --git a/core-java-modules/core-java-lang-math-4/pom.xml b/core-java-modules/core-java-lang-math-4/pom.xml new file mode 100644 index 0000000000..e818855d36 --- /dev/null +++ b/core-java-modules/core-java-lang-math-4/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + core-java-lang-math-4 + core-java-lang-math-4 + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + + + diff --git a/core-java-modules/core-java-lang-math-4/src/test/java/com/baeldung/percentile/CalculatePercentileUnitTest.java b/core-java-modules/core-java-lang-math-4/src/test/java/com/baeldung/percentile/CalculatePercentileUnitTest.java new file mode 100644 index 0000000000..7b46b37e38 --- /dev/null +++ b/core-java-modules/core-java-lang-math-4/src/test/java/com/baeldung/percentile/CalculatePercentileUnitTest.java @@ -0,0 +1,78 @@ +package com.baeldung.percentile; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.Test; + +public class CalculatePercentileUnitTest { + + public static > T getPercentile(Collection input, double percentile) { + if (input == null || input.isEmpty()) { + throw new IllegalArgumentException("The input dataset cannot be null or empty."); + } + if (percentile < 0 || percentile > 100) { + throw new IllegalArgumentException("Percentile must be between 0 and 100(exclusive)"); + } + List sortedList = input.stream() + .sorted() + .collect(Collectors.toList()); + + int rank = percentile == 0 ? 1 : (int) Math.ceil(percentile / 100.0 * input.size()); + return sortedList.get(rank - 1); + } + + @Test + void whenCallingGetPercentileWithAList_thenGetExpectedResult() { + assertThrows(IllegalArgumentException.class, () -> getPercentile(List.of(1, 2, 3), -1)); + assertThrows(IllegalArgumentException.class, () -> getPercentile(List.of(1, 2, 3), 101)); + + List list100 = IntStream.rangeClosed(1, 100) + .boxed() + .collect(Collectors.toList()); + Collections.shuffle(list100); + + assertEquals(1, getPercentile(list100, 0)); + assertEquals(10, getPercentile(list100, 10)); + assertEquals(25, getPercentile(list100, 25)); + assertEquals(50, getPercentile(list100, 50)); + assertEquals(76, getPercentile(list100, 75.3)); + assertEquals(100, getPercentile(list100, 100)); + + List list8 = IntStream.of(-1, 200, 30, 42, -5, 7, 8, 92) + .boxed() + .collect(Collectors.toList()); + + assertEquals(-5, getPercentile(list8, 0)); + assertEquals(-5, getPercentile(list8, 10)); + assertEquals(-1, getPercentile(list8, 25)); + assertEquals(8, getPercentile(list8, 50)); + assertEquals(92, getPercentile(list8, 75.3)); + assertEquals(200, getPercentile(list8, 100)); + } + + @Test + void whenCallingGetPercentileWithAnArray_thenGetExpectedResult() { + + long[] theArray = new long[] { -1, 200, 30, 42, -5, 7, 8, 92 }; + + //convert the long[] array to a List + List list8 = Arrays.stream(theArray) + .boxed() + .toList(); + + assertEquals(-5, getPercentile(list8, 0)); + assertEquals(-5, getPercentile(list8, 10)); + assertEquals(-1, getPercentile(list8, 25)); + assertEquals(8, getPercentile(list8, 50)); + assertEquals(92, getPercentile(list8, 75.3)); + assertEquals(200, getPercentile(list8, 100)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-math/pom.xml b/core-java-modules/core-java-lang-math/pom.xml index 85e653930c..c8d261818a 100644 --- a/core-java-modules/core-java-lang-math/pom.xml +++ b/core-java-modules/core-java-lang-math/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-math - core-java-lang-math jar + core-java-lang-math com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-oop-constructors-2/README.md b/core-java-modules/core-java-lang-oop-constructors-2/README.md index d9b162c7a6..1357dfc1c5 100644 --- a/core-java-modules/core-java-lang-oop-constructors-2/README.md +++ b/core-java-modules/core-java-lang-oop-constructors-2/README.md @@ -4,4 +4,5 @@ This module contains article about constructors in Java ### Relevant Articles: - [Different Ways to Create an Object in Java](https://www.baeldung.com/java-different-ways-to-create-objects) -- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-oop-constructors) \ No newline at end of file +- [When to Use Setter Methods or Constructors for Setting a Variable’s Value in Java](https://www.baeldung.com/java-setter-method-vs-constructor) +- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-oop-constructors) diff --git a/core-java-modules/core-java-lang-oop-constructors-2/pom.xml b/core-java-modules/core-java-lang-oop-constructors-2/pom.xml index c6d9d84774..d1a1288cc9 100644 --- a/core-java-modules/core-java-lang-oop-constructors-2/pom.xml +++ b/core-java-modules/core-java-lang-oop-constructors-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-constructors-2 - core-java-lang-oop-constructors-2 jar + core-java-lang-oop-constructors-2 core-java-modules diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java new file mode 100644 index 0000000000..f8c04a3f81 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java @@ -0,0 +1,26 @@ +package com.baeldung.constructorversussettermethod; + +public class Product { + private String name; + private double price; + private String category; + + public Product(String name, double price, String category) { + this.name = name; + this.price = price; + this.category = category; + } + + public String getName() { + return name; + } + + public double getPrice() { + return price; + } + + public String getCategory() { + return category; + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java new file mode 100644 index 0000000000..57ec590470 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java @@ -0,0 +1,31 @@ +package com.baeldung.constructorversussettermethod; + +public class User { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + if (username.matches("[a-zA-Z0-9_]+")) { + this.username = username; + } else { + throw new IllegalArgumentException("Invalid username format"); + } + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + if (password.length() >= 8) { + this.password = password; + } else { + throw new IllegalArgumentException("Password must be at least 8 characters long"); + } + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java b/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java new file mode 100644 index 0000000000..09294e2232 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.constructorversussettermethod; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ConstructorsVersusSetterMethodsUnitTest { + @Test + public void givenNewUser_whenSettingUsername_thenUsernameIsSet() { + User user = new User(); + user.setUsername("john_doe"); + assertEquals("john_doe", user.getUsername()); + } + + @Test + public void givenNewUser_whenSettingPassword_thenPasswordIsSet() { + User user = new User(); + user.setPassword("strongPassword123"); + assertEquals("strongPassword123", user.getPassword()); + } + + @Test + public void givenProductDetails_whenCreatingProductWithConstructor_thenProductHasCorrectAttributes() { + Product product = new Product("Smartphone", 599.99, "Electronics"); + assertEquals("Smartphone", product.getName()); + assertEquals(599.99, product.getPrice(), 0.001); + assertEquals("Electronics", product.getCategory()); + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors/pom.xml b/core-java-modules/core-java-lang-oop-constructors/pom.xml index 061b3c08de..39e6c86821 100644 --- a/core-java-modules/core-java-lang-oop-constructors/pom.xml +++ b/core-java-modules/core-java-lang-oop-constructors/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-constructors - core-java-lang-oop-constructors jar + core-java-lang-oop-constructors core-java-modules diff --git a/core-java-modules/core-java-lang-oop-generics/pom.xml b/core-java-modules/core-java-lang-oop-generics/pom.xml index 9c453cae10..035c82324a 100644 --- a/core-java-modules/core-java-lang-oop-generics/pom.xml +++ b/core-java-modules/core-java-lang-oop-generics/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-generics - core-java-lang-oop-generics jar + core-java-lang-oop-generics core-java-modules diff --git a/core-java-modules/core-java-lang-oop-inheritance/pom.xml b/core-java-modules/core-java-lang-oop-inheritance/pom.xml index 4fc7e14d84..fe467545eb 100644 --- a/core-java-modules/core-java-lang-oop-inheritance/pom.xml +++ b/core-java-modules/core-java-lang-oop-inheritance/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-inheritance - core-java-lang-oop-inheritance jar + core-java-lang-oop-inheritance core-java-modules diff --git a/core-java-modules/core-java-lang-oop-methods/pom.xml b/core-java-modules/core-java-lang-oop-methods/pom.xml index 5597cff0ae..39207d71ed 100644 --- a/core-java-modules/core-java-lang-oop-methods/pom.xml +++ b/core-java-modules/core-java-lang-oop-methods/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-methods - core-java-lang-oop-methods jar + core-java-lang-oop-methods core-java-modules diff --git a/core-java-modules/core-java-lang-oop-modifiers/pom.xml b/core-java-modules/core-java-lang-oop-modifiers/pom.xml index 459aa21721..c1b3c7d308 100644 --- a/core-java-modules/core-java-lang-oop-modifiers/pom.xml +++ b/core-java-modules/core-java-lang-oop-modifiers/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-modifiers - core-java-lang-oop-modifiers jar + core-java-lang-oop-modifiers core-java-modules diff --git a/core-java-modules/core-java-lang-oop-others/pom.xml b/core-java-modules/core-java-lang-oop-others/pom.xml index dea92067f2..9e208a077b 100644 --- a/core-java-modules/core-java-lang-oop-others/pom.xml +++ b/core-java-modules/core-java-lang-oop-others/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-others - core-java-lang-oop-others jar + core-java-lang-oop-others core-java-modules diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java new file mode 100644 index 0000000000..6b8fda032c --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java @@ -0,0 +1,14 @@ +package com.baeldung.statementsbeforesuper; + +class Child extends Parent { + Child() { + super(); // Or super(10); Correct placements + System.out.println("Child constructor"); + additionalInitialization(); + // super(); Compilation error: Constructor call must be the first statement in a constructor + } + + private void additionalInitialization() { + System.out.println("Additional initialization in Child"); + } +} diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java new file mode 100644 index 0000000000..38ed9ecd1a --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java @@ -0,0 +1,11 @@ +package com.baeldung.statementsbeforesuper; + +public class Parent { + public Parent(int id) { + System.out.println("Parametrized Parent constructor"); + } + + public Parent() { + System.out.println("Parent constructor"); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/pom.xml b/core-java-modules/core-java-lang-oop-patterns/pom.xml index f0a714e911..3c1f94954a 100644 --- a/core-java-modules/core-java-lang-oop-patterns/pom.xml +++ b/core-java-modules/core-java-lang-oop-patterns/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-patterns - core-java-lang-oop-patterns jar + core-java-lang-oop-patterns core-java-modules diff --git a/core-java-modules/core-java-lang-oop-types/pom.xml b/core-java-modules/core-java-lang-oop-types/pom.xml index a9909598eb..9d36beb13e 100644 --- a/core-java-modules/core-java-lang-oop-types/pom.xml +++ b/core-java-modules/core-java-lang-oop-types/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-oop-types - core-java-lang-oop-types jar + core-java-lang-oop-types core-java-modules diff --git a/core-java-modules/core-java-lang-operators-2/README.md b/core-java-modules/core-java-lang-operators-2/README.md index 52b05e95a4..0dc6f7d303 100644 --- a/core-java-modules/core-java-lang-operators-2/README.md +++ b/core-java-modules/core-java-lang-operators-2/README.md @@ -12,3 +12,4 @@ This module contains articles about Java operators - [What Does “––>” Mean in Java?](https://www.baeldung.com/java-minus-minus-greaterthan) - [All the Ways Java Uses the Colon Character](https://www.baeldung.com/java-colon) - [Convert Infix to Postfix Expressions in Java](https://www.baeldung.com/java-convert-infix-to-postfix-expressions) +- [Representation of Integers at a Bit Level in Java](https://www.baeldung.com/java-integer-bit-representation) diff --git a/core-java-modules/core-java-lang-operators-2/pom.xml b/core-java-modules/core-java-lang-operators-2/pom.xml index 4170f9f6a0..301f549011 100644 --- a/core-java-modules/core-java-lang-operators-2/pom.xml +++ b/core-java-modules/core-java-lang-operators-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-operators-2 - core-java-lang-operators-2 jar + core-java-lang-operators-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/integersatbitlevel/IntegersBitLevelUnitTest.java b/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/integersatbitlevel/IntegersBitLevelUnitTest.java new file mode 100644 index 0000000000..54c0b89d03 --- /dev/null +++ b/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/integersatbitlevel/IntegersBitLevelUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.integersatbitlevel; + +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; + +class IntegersBitLevelUnitTest { + + @Test + void givenNumbers_whenBitwiseAND_thenResultIsExpected() { + int result = 0b1100 & 0b0111; + assertEquals(0b0100, result); + } + + @Test + void givenNumbers_whenBitwiseOR_thenResultIsExpected() { + int result = 0b1100 | 0b0111; + assertEquals(0b1111, result); + } + + @Test + void givenNumbers_whenBitwiseXOR_thenResultIsExpected() { + int result = 0b1100 ^ 0b0111; + assertEquals(0b1011, result); + } + + @Test + void givenNumber_whenBitwiseNOT_thenResultIsExpected() { + int result = ~0b0101; + assertEquals(-0b0110, result); + } + + @Test + void givenNumber_whenBitwiseLeftShift_thenResultIsExpected() { + int result = 0b0101 << 2; + assertEquals(0b10100, result); + } + + @Test + void givenNumber_whenBitwiseRightShift_thenResultIsExpected() { + int result = 0b0101 >> 1; + assertEquals(0b10, result); + } + + @Test + void givenOriginalColor_whenApplyingMask_thenObtainModifiedColor() { + int originalColor = 0xFF336699; + + int alphaMask = 0xFF000000; + int redMask = 0x00FF0000; + int greenMask = 0x0000FF00; + int blueMask = 0x000000FF; + + int alpha = (originalColor & alphaMask) >>> 24; + int red = (originalColor & redMask) >>> 16; + int green = (originalColor & greenMask) >>> 8; + int blue = originalColor & blueMask; + + red = Math.min(255, red + 50); + green = Math.min(255, green + 30); + + int modifiedColor = (alpha << 24) | (red << 16) | (green << 8) | blue; + + assertEquals(-10124135, modifiedColor); + } +} diff --git a/core-java-modules/core-java-lang-operators/pom.xml b/core-java-modules/core-java-lang-operators/pom.xml index 1815d01dcc..1ea35da281 100644 --- a/core-java-modules/core-java-lang-operators/pom.xml +++ b/core-java-modules/core-java-lang-operators/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-operators - core-java-lang-operators jar + core-java-lang-operators com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-syntax-2/pom.xml b/core-java-modules/core-java-lang-syntax-2/pom.xml index bae5f0b6bd..b5d41958b7 100644 --- a/core-java-modules/core-java-lang-syntax-2/pom.xml +++ b/core-java-modules/core-java-lang-syntax-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-syntax-2 - core-java-lang-syntax-2 jar + core-java-lang-syntax-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-lang-syntax/pom.xml b/core-java-modules/core-java-lang-syntax/pom.xml index 4e1b534110..5d366194de 100644 --- a/core-java-modules/core-java-lang-syntax/pom.xml +++ b/core-java-modules/core-java-lang-syntax/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang-syntax - core-java-lang-syntax jar + core-java-lang-syntax com.baeldung.core-java-modules @@ -13,9 +13,6 @@ 0.0.1-SNAPSHOT - - - core-java-lang-syntax diff --git a/core-java-modules/core-java-lang/pom.xml b/core-java-modules/core-java-lang/pom.xml index 27cf0ac276..7e0606b47f 100644 --- a/core-java-modules/core-java-lang/pom.xml +++ b/core-java-modules/core-java-lang/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-lang - core-java-lang jar + core-java-lang com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-locale/pom.xml b/core-java-modules/core-java-locale/pom.xml index f4fd823444..9f3368c659 100644 --- a/core-java-modules/core-java-locale/pom.xml +++ b/core-java-modules/core-java-locale/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-locale 0.1.0-SNAPSHOT - core-java-locale jar + core-java-locale com.baeldung.core-java-modules @@ -14,7 +14,4 @@ 0.0.1-SNAPSHOT - - - \ No newline at end of file diff --git a/core-java-modules/core-java-loops/pom.xml b/core-java-modules/core-java-loops/pom.xml index c9ce86f54b..a4969aaa0a 100644 --- a/core-java-modules/core-java-loops/pom.xml +++ b/core-java-modules/core-java-loops/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-loops - core-java-loops jar + core-java-loops com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-methods/pom.xml b/core-java-modules/core-java-methods/pom.xml index 5502cc6733..58b2ad6ebe 100644 --- a/core-java-modules/core-java-methods/pom.xml +++ b/core-java-modules/core-java-methods/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-methods 0.1.0-SNAPSHOT - core-java-methods jar + core-java-methods com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-networking-2/pom.xml b/core-java-modules/core-java-networking-2/pom.xml index 388e439e37..77ddd94fdc 100644 --- a/core-java-modules/core-java-networking-2/pom.xml +++ b/core-java-modules/core-java-networking-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-networking-2 - core-java-networking-2 jar + core-java-networking-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java similarity index 77% rename from core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java rename to core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java index 5e295e65a0..edafe242c1 100644 --- a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java +++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java @@ -6,33 +6,33 @@ import java.io.IOException; import org.junit.Test; -public class UrlCheckerUnitTest { +public class UrlCheckerIntegrationTest { @Test public void givenValidUrl_WhenUsingHEAD_ThenReturn200() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com"); + int responseCode = tester.getResponseCodeForURLUsingHead("https://httpbin.org/status/200"); assertEquals(200, responseCode); } @Test public void givenInvalidIUrl_WhenUsingHEAD_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com/unkownurl"); + int responseCode = tester.getResponseCodeForURLUsingHead("https://httpbin.org/status/404"); assertEquals(404, responseCode); } @Test public void givenValidUrl_WhenUsingGET_ThenReturn200() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURL("http://www.example.com"); + int responseCode = tester.getResponseCodeForURL("https://httpbin.org/status/200"); assertEquals(200, responseCode); } @Test public void givenInvalidIUrl_WhenUsingGET_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURL("http://www.example.com/unkownurl"); + int responseCode = tester.getResponseCodeForURL("https://httpbin.org/status/404"); assertEquals(404, responseCode); } diff --git a/core-java-modules/core-java-networking-3/pom.xml b/core-java-modules/core-java-networking-3/pom.xml index 6d0374c598..26cfd206c0 100644 --- a/core-java-modules/core-java-networking-3/pom.xml +++ b/core-java-modules/core-java-networking-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-networking-3 - core-java-networking-3 jar + core-java-networking-3 com.baeldung.core-java-modules @@ -52,12 +52,6 @@ java-ipv6 ${googlecode.ipv6.version} - - - com.google.guava - guava - ${guava.version} - commons-validator diff --git a/core-java-modules/core-java-networking-4/README.md b/core-java-modules/core-java-networking-4/README.md index 88eed162af..13b82f6c10 100644 --- a/core-java-modules/core-java-networking-4/README.md +++ b/core-java-modules/core-java-networking-4/README.md @@ -8,4 +8,5 @@ - [Normalize a URL in Java](https://www.baeldung.com/java-url-normalization) - [Translating Space Characters in URLEncoder](https://www.baeldung.com/java-urlencoder-translate-space-characters) - [Creating a Custom URL Connection](https://www.baeldung.com/java-custom-url-connection) -- [[<-- Prev]](/core-java-modules/core-java-networking-3) \ No newline at end of file +- [Obtaining the Last Path Segment of a URI in Java](https://www.baeldung.com/java-uri-get-last-path-segment) +- [[<-- Prev]](/core-java-modules/core-java-networking-3) diff --git a/core-java-modules/core-java-networking-4/pom.xml b/core-java-modules/core-java-networking-4/pom.xml index acdbf37c63..2ae1ea9068 100644 --- a/core-java-modules/core-java-networking-4/pom.xml +++ b/core-java-modules/core-java-networking-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-networking-4 - core-java-networking-4 jar + core-java-networking-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-networking-4/src/test/java/com/baeldung/obtainlastsegmentofurl/ObtainLastSegmentOfURLUnitTest.java b/core-java-modules/core-java-networking-4/src/test/java/com/baeldung/obtainlastsegmentofurl/ObtainLastSegmentOfURLUnitTest.java new file mode 100644 index 0000000000..153e37dbda --- /dev/null +++ b/core-java-modules/core-java-networking-4/src/test/java/com/baeldung/obtainlastsegmentofurl/ObtainLastSegmentOfURLUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.obtainlastsegmentofurl; + +import org.apache.commons.io.FilenameUtils; + +import org.junit.Test; + +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class ObtainLastSegmentOfURLUnitTest { + @Test + public void givenURL_whenUsingURIClass_thenGetLastPathSegment() throws URISyntaxException { + URI uri = new URI("https://www.example.com/path/to/resource"); + String path = uri.getPath(); + + String[] segments = path.split("/"); + String lastSegment = segments[segments.length - 1]; + + assertEquals("resource", lastSegment); + } + + @Test + public void givenURL_whenUsingPathClass_thenGetLastPathSegment() { + String exampleURI = "https://www.example.com/path/to/resource"; + + try { + URI uri = new URI(exampleURI); + String pathString = uri.getPath(); + Path path = Paths.get(pathString); + Path lastSegment = path.getName(path.getNameCount() - 1); + + assertEquals("resource", lastSegment.toString()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void givenURL_whenUsingRegularExpression_thenGetLastPathSegment() throws URISyntaxException { + URI uri = new URI("https://www.example.com/path/to/resource"); + String path = uri.getPath(); + + Pattern pattern = Pattern.compile(".*/(.+)"); + Matcher matcher = pattern.matcher(path); + + if (!matcher.find()) { + fail("Regex pattern didn't match."); + } + + String lastSegment = matcher.group(1); + assertEquals("resource", lastSegment); + } + + @Test + public void givenURL_whenUsingFilenameUtilsClass_thenGetLastPathSegment() throws URISyntaxException { + String exampleURI = "https://www.example.com/path/to/resource"; + + URI uri = new URI(exampleURI); + String path = uri.getPath(); + + String lastSegment = FilenameUtils.getName(path); + + assertEquals("resource", lastSegment); + } +} diff --git a/core-java-modules/core-java-networking/pom.xml b/core-java-modules/core-java-networking/pom.xml index 5c959c62be..2028d9b218 100644 --- a/core-java-modules/core-java-networking/pom.xml +++ b/core-java-modules/core-java-networking/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-networking - core-java-networking jar + core-java-networking com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-nio-2/pom.xml b/core-java-modules/core-java-nio-2/pom.xml index dde708c10d..f1360247b3 100644 --- a/core-java-modules/core-java-nio-2/pom.xml +++ b/core-java-modules/core-java-nio-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-nio-2 - core-java-nio-2 jar + core-java-nio-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-nio/pom.xml b/core-java-modules/core-java-nio/pom.xml index 35fef82df5..55dff63230 100644 --- a/core-java-modules/core-java-nio/pom.xml +++ b/core-java-modules/core-java-nio/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-nio - core-java-nio jar + core-java-nio com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-numbers-2/README.md b/core-java-modules/core-java-numbers-2/README.md index 54f6cf30e8..59d29a9d74 100644 --- a/core-java-modules/core-java-numbers-2/README.md +++ b/core-java-modules/core-java-numbers-2/README.md @@ -13,4 +13,5 @@ This module contains articles about numbers in Java. - [Binary Numbers in Java](https://www.baeldung.com/java-binary-numbers) - [Finding the Least Common Multiple in Java](https://www.baeldung.com/java-least-common-multiple) - [Binary Numbers in Java](https://www.baeldung.com/java-binary-numbers) +- [RGB Representation as an Integer in Java](https://www.baeldung.com/java-rgb-color-representation) - More articles: [[<-- prev]](../core-java-numbers) [[next -->]](../core-java-numbers-3) diff --git a/core-java-modules/core-java-numbers-2/pom.xml b/core-java-modules/core-java-numbers-2/pom.xml index 46e0fa47b4..987f140c67 100644 --- a/core-java-modules/core-java-numbers-2/pom.xml +++ b/core-java-modules/core-java-numbers-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-2 - core-java-numbers-2 jar + core-java-numbers-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-numbers-3/pom.xml b/core-java-modules/core-java-numbers-3/pom.xml index 8acdaa6be4..28036faf5e 100644 --- a/core-java-modules/core-java-numbers-3/pom.xml +++ b/core-java-modules/core-java-numbers-3/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-3 - core-java-numbers-3 jar + core-java-numbers-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-numbers-4/pom.xml b/core-java-modules/core-java-numbers-4/pom.xml index 4fe8b292da..8633b06f3d 100644 --- a/core-java-modules/core-java-numbers-4/pom.xml +++ b/core-java-modules/core-java-numbers-4/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-4 - core-java-numbers-4 jar + core-java-numbers-4 com.baeldung.core-java-modules @@ -23,11 +23,6 @@ commons-lang3 ${commons-lang3.version} - - com.google.guava - guava - ${guava.version} -
diff --git a/core-java-modules/core-java-numbers-5/pom.xml b/core-java-modules/core-java-numbers-5/pom.xml index c72ba66bff..e2bd67896f 100644 --- a/core-java-modules/core-java-numbers-5/pom.xml +++ b/core-java-modules/core-java-numbers-5/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-5 - core-java-numbers-5 jar + core-java-numbers-5 com.baeldung.core-java-modules @@ -24,11 +24,6 @@ commons-lang3 ${commons-lang3.version}
- - com.google.guava - guava - ${guava.version} - diff --git a/core-java-modules/core-java-numbers-6/pom.xml b/core-java-modules/core-java-numbers-6/pom.xml index a5ddcfc0ee..95d01648a3 100644 --- a/core-java-modules/core-java-numbers-6/pom.xml +++ b/core-java-modules/core-java-numbers-6/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-6 - core-java-numbers-6 jar + core-java-numbers-6 com.baeldung.core-java-modules @@ -25,11 +25,6 @@ ${commons-codec} test - - com.google.guava - guava - ${guava.version} - diff --git a/core-java-modules/core-java-numbers-7/README.md b/core-java-modules/core-java-numbers-7/README.md index 271f4833e3..ab3532fc20 100644 --- a/core-java-modules/core-java-numbers-7/README.md +++ b/core-java-modules/core-java-numbers-7/README.md @@ -3,3 +3,4 @@ - [Print a Double Value Without Scientific Notation in Java](https://www.baeldung.com/java-print-double-number-no-scientific-notation) - [Check if a Float Value is Equivalent to an Integer Value in Java](https://www.baeldung.com/java-float-integer-equal) - [Generating Unique Positive Long Using SecureRandom in Java](https://www.baeldung.com/java-securerandom-generate-positive-long) +- [BigDecimal.ZERO vs. new BigDecimal(0)](https://www.baeldung.com/java-bigdecimal-zero-vs-new) diff --git a/core-java-modules/core-java-numbers-7/pom.xml b/core-java-modules/core-java-numbers-7/pom.xml index 3940a0b1d0..636113897e 100644 --- a/core-java-modules/core-java-numbers-7/pom.xml +++ b/core-java-modules/core-java-numbers-7/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers-7 - core-java-numbers-7 jar + core-java-numbers-7 com.baeldung.core-java-modules @@ -19,11 +19,6 @@ ${junit-jupiter.version} test - - com.google.guava - guava - ${guava.version} - diff --git a/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumber.java b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumber.java new file mode 100644 index 0000000000..c969e43f86 --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumber.java @@ -0,0 +1,43 @@ +import java.util.Map; + +public class UseHashMapToConvertPhoneNumberInWordsToNumber { + private static Map multipliers = Map.of("double",2, + "triple", 3, + "quadruple", 4); + private static Map digits = Map.of("zero","1", + "one", "1", + "two", "2", + "three", "3", + "four", "4", + "five", "5", + "six", "6", + "seven", "7", + "eight", "8", + "nine", "9"); + + + public static String convertPhoneNumberInWordsToNumber(String phoneNumberInWord) { + + StringBuilder output = new StringBuilder(); + Integer currentMultiplier = null; + String[] words = phoneNumberInWord.split(" "); + + for (String word : words) { + Integer multiplier = multipliers.get(word); + if (multiplier != null) { + if (currentMultiplier != null) { + throw new IllegalArgumentException("Cannot have consecutive multipliers, at: " + word); + } + currentMultiplier = multiplier; + } else { + String digit = digits.get(word); + if (digit == null) { + throw new IllegalArgumentException("Invalid word: " + word); + } + output.append(digit.repeat(currentMultiplier != null ? currentMultiplier : 1)); + currentMultiplier = null; + } + } + return output.toString(); + } +} diff --git a/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumber.java b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumber.java new file mode 100644 index 0000000000..69f9ce9ab7 --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumber.java @@ -0,0 +1,64 @@ +public class UseSwitchToConvertPhoneNumberInWordsToNumber { + + public static String convertPhoneNumberInWordsToNumber(String phoneNumberInWord) { + + StringBuilder output = new StringBuilder(); + Integer currentMultiplier = null; + String[] words = phoneNumberInWord.split(" "); + + for (String word : words) { + Integer multiplier = getWordAsMultiplier(word); + if (multiplier != null) { + if (currentMultiplier != null) { + throw new IllegalArgumentException("Cannot have consecutive multipliers, at: " + word); + } + currentMultiplier = multiplier; + } else { + output.append(getWordAsDigit(word).repeat(currentMultiplier != null ? currentMultiplier : 1)); + currentMultiplier = null; + } + } + return output.toString(); + } + + public static Integer getWordAsMultiplier(String word) { + switch (word) { + case "double": + return 2; + case "triple": + return 3; + case "quadruple": + return 4; + default: + return null; + } + } + + public static String getWordAsDigit(String word) { + switch (word) { + case "zero": + return "0"; + case "one": + return "1"; + case "two": + return "2"; + case "three": + return "3"; + case "four": + return "4"; + case "five": + return "5"; + case "six": + return "6"; + case "seven": + return "7"; + case "eight": + return "8"; + case "nine": + return "9"; + default: + throw new IllegalArgumentException("Invalid word: " + word); + } + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumberUnitTest.java b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumberUnitTest.java new file mode 100644 index 0000000000..95a50dd16e --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseHashMapToConvertPhoneNumberInWordsToNumberUnitTest.java @@ -0,0 +1,31 @@ +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class UseHashMapToConvertPhoneNumberInWordsToNumberUnitTest { + + @Test + void givenStringWithWhiteSpaces_WhenConvertPhoneNumberInWordsToNumber_ThenEquivalentNumber() { + + assertEquals("5248888", + UseHashMapToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five two four quadruple eight")); + } + + @Test + void givenStringEndingWithConseutiveMultipliers_WhenConvertPhoneNumberInWordsToNumber_ThenThrowException() { + + assertThrows(IllegalArgumentException.class, () -> { + UseHashMapToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five eight three double triple"); + }); + } + + @Test + void givenStringWithInvalidWords_WhenConvertPhoneNumberInWordsToNumber_ThenThrowException() { + + assertThrows(IllegalArgumentException.class, () -> { + UseHashMapToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five eight three two four penta null eight"); + }); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumberUnitTest.java b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumberUnitTest.java new file mode 100644 index 0000000000..093e96ecea --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/convertphonenumberinwordstonumber/UseSwitchToConvertPhoneNumberInWordsToNumberUnitTest.java @@ -0,0 +1,62 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class UseSwitchToConvertPhoneNumberInWordsToNumberUnitTest { + + @Test + void givenStringWithWhiteSpaces_WhenConvertPhoneNumberInWordsToNumber_ThenEquivalentNumber() { + + assertEquals("5248888", + UseSwitchToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five two four quadruple eight")); + + } + + @Test + void givenStringEndingWithConseutiveMultipliers_WhenConvertPhoneNumberInWordsToNumber_ThenThrowException() { + + assertThrows(IllegalArgumentException.class, () -> { + UseSwitchToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five eight three double triple"); + }); + } + + @Test + void givenStringWithInvalidWords_WhenConvertPhoneNumberInWordsToNumber_ThenThrowException() { + + assertThrows(IllegalArgumentException.class, () -> { + UseSwitchToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("five eight three two four penta null eight"); + }); + } + + + @Test + void givenString_WhenGetWordAsMultiplier_ThenEquivalentNumber() { + assertEquals(2, UseSwitchToConvertPhoneNumberInWordsToNumber + .getWordAsMultiplier("double")); + } + + @Test + void givenInvalidString_WhenGetWordAsMultiplier_ThenReturnNull() { + assertEquals(null, UseSwitchToConvertPhoneNumberInWordsToNumber + .getWordAsMultiplier("hexa")); + + } + + @Test + void givenString_WhenMapIndividualDigits_ThenEquivalentNumber() { + assertEquals("5", + UseSwitchToConvertPhoneNumberInWordsToNumber + .getWordAsDigit("five")); + } + + @Test + void givenInvalidString_WhenMapIndividualDigits_ThenThrowException() { + assertThrows(IllegalArgumentException.class, () -> { + UseSwitchToConvertPhoneNumberInWordsToNumber + .convertPhoneNumberInWordsToNumber("penta"); + }); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-conversions/README.md b/core-java-modules/core-java-numbers-conversions/README.md index 9f2a1d07b8..334d9c1f6e 100644 --- a/core-java-modules/core-java-numbers-conversions/README.md +++ b/core-java-modules/core-java-numbers-conversions/README.md @@ -6,5 +6,6 @@ - [Converting from float to BigDecimal in Java](https://www.baeldung.com/java-convert-float-bigdecimal) - [Convert Positive Integer to Negative and Vice Versa in Java](https://www.baeldung.com/java-negating-integer) - [Rounding Up a Number to Nearest Multiple of 5 in Java](https://www.baeldung.com/java-round-nearest-multiple-five) -- [Convert byte to int Type in Java](https://www.baeldung.com/java-byte-to-int-conversion) -- [Converting Integer to BigDecimal in Java](https://www.baeldung.com/java-integer-bigdecimal-conversion) +- [Convert byte to int Type in Java](https://www.baeldung.com/java-byte-integer-conversion) +- [Converting BigDecimal to Integer in Java](https://www.baeldung.com/java-integer-bigdecimal-conversion) +- [Converting Integer to BigDecimal in Java](https://www.baeldung.com/java-from-integer-to-bigdecimal) diff --git a/core-java-modules/core-java-numbers-conversions/pom.xml b/core-java-modules/core-java-numbers-conversions/pom.xml index 43809e8453..0cbd5823fe 100644 --- a/core-java-modules/core-java-numbers-conversions/pom.xml +++ b/core-java-modules/core-java-numbers-conversions/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-conversions.0.0.xsd"> 4.0.0 core-java-numbers-conversions - core-java-numbers-conversions jar + core-java-numbers-conversions com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-numbers/pom.xml b/core-java-modules/core-java-numbers/pom.xml index 1240245ba3..debc90638e 100644 --- a/core-java-modules/core-java-numbers/pom.xml +++ b/core-java-modules/core-java-numbers/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-numbers - core-java-numbers jar + core-java-numbers com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-optional/pom.xml b/core-java-modules/core-java-optional/pom.xml index c676827427..7c1d873b46 100644 --- a/core-java-modules/core-java-optional/pom.xml +++ b/core-java-modules/core-java-optional/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-optional - core-java-optional jar + core-java-optional com.baeldung.core-java-modules @@ -54,7 +54,7 @@ 6.4.2.Final - 5.3.2 + 5.4.0 \ No newline at end of file diff --git a/core-java-modules/core-java-os-2/pom.xml b/core-java-modules/core-java-os-2/pom.xml index 27dc8a0c8b..9827ee2b47 100644 --- a/core-java-modules/core-java-os-2/pom.xml +++ b/core-java-modules/core-java-os-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-os-2 - core-java-os-2 jar + core-java-os-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-os/pom.xml b/core-java-modules/core-java-os/pom.xml index 17b0d1a058..58ccaea4c9 100644 --- a/core-java-modules/core-java-os/pom.xml +++ b/core-java-modules/core-java-os/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-os - core-java-os jar + core-java-os com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-perf-2/pom.xml b/core-java-modules/core-java-perf-2/pom.xml index a44f6aa8c1..a17180edbe 100644 --- a/core-java-modules/core-java-perf-2/pom.xml +++ b/core-java-modules/core-java-perf-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-perf-2 - core-java-perf-2 jar + core-java-perf-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-perf/pom.xml b/core-java-modules/core-java-perf/pom.xml index c21fc94ec1..026e0692d1 100644 --- a/core-java-modules/core-java-perf/pom.xml +++ b/core-java-modules/core-java-perf/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-perf - core-java-perf jar + core-java-perf com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-properties/pom.xml b/core-java-modules/core-java-properties/pom.xml index 9beacabdd5..67e0204c6e 100644 --- a/core-java-modules/core-java-properties/pom.xml +++ b/core-java-modules/core-java-properties/pom.xml @@ -5,8 +5,8 @@ 4.0.0 core-java-properties 0.1.0-SNAPSHOT - core-java-properties jar + core-java-properties com.baeldung.core-java-modules @@ -14,10 +14,4 @@ 0.0.1-SNAPSHOT - - - - - - \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-2/pom.xml b/core-java-modules/core-java-reflection-2/pom.xml index c7a4981533..41d2b0a7ae 100644 --- a/core-java-modules/core-java-reflection-2/pom.xml +++ b/core-java-modules/core-java-reflection-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-reflection-2 - core-java-reflection-2 jar + core-java-reflection-2 com.baeldung.core-java-modules @@ -49,7 +49,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + ${jacoco-maven-plugin.version} @@ -73,6 +73,7 @@ 1.8 1.8 5.3.4 + 0.8.11 \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-3/pom.xml b/core-java-modules/core-java-reflection-3/pom.xml index e60652f1f2..61bc424336 100644 --- a/core-java-modules/core-java-reflection-3/pom.xml +++ b/core-java-modules/core-java-reflection-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-reflection-3 - core-java-reflection-3 jar + core-java-reflection-3 com.baeldung.core-java-modules @@ -49,7 +49,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + ${jacoco-maven-plugin.version} @@ -73,6 +73,7 @@ 1.8 1.8 5.3.4 + 0.8.11 \ No newline at end of file diff --git a/core-java-modules/core-java-reflection/pom.xml b/core-java-modules/core-java-reflection/pom.xml index f77c791936..a58d18c03f 100644 --- a/core-java-modules/core-java-reflection/pom.xml +++ b/core-java-modules/core-java-reflection/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-reflection - core-java-reflection jar + core-java-reflection com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-regex-2/pom.xml b/core-java-modules/core-java-regex-2/pom.xml index ddfba35cb2..83280bd310 100644 --- a/core-java-modules/core-java-regex-2/pom.xml +++ b/core-java-modules/core-java-regex-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-regex-2 - core-java-regex-2 jar + core-java-regex-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-regex-3/pom.xml b/core-java-modules/core-java-regex-3/pom.xml index 143b615246..b3e1019119 100644 --- a/core-java-modules/core-java-regex-3/pom.xml +++ b/core-java-modules/core-java-regex-3/pom.xml @@ -4,7 +4,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-regex-3 + jar core-java-regex-3 + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + + org.junit.jupiter @@ -13,12 +21,5 @@ test - jar - - - com.baeldung.core-java-modules - core-java-modules - 0.0.1-SNAPSHOT - \ No newline at end of file diff --git a/core-java-modules/core-java-regex/pom.xml b/core-java-modules/core-java-regex/pom.xml index 00b8107c57..ca7fb38634 100644 --- a/core-java-modules/core-java-regex/pom.xml +++ b/core-java-modules/core-java-regex/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-regex - core-java-regex jar + core-java-regex com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-scanner/pom.xml b/core-java-modules/core-java-scanner/pom.xml index bb5c7dca78..9fb9d4ee05 100644 --- a/core-java-modules/core-java-scanner/pom.xml +++ b/core-java-modules/core-java-scanner/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-scanner - core-java-scanner jar + core-java-scanner com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml index b54afc31d8..a7f47d2ff5 100644 --- a/core-java-modules/core-java-security-2/pom.xml +++ b/core-java-modules/core-java-security-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-security-2 - core-java-security-2 jar + core-java-security-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-security-3/pom.xml b/core-java-modules/core-java-security-3/pom.xml index dae570e51d..3ca0cf62aa 100644 --- a/core-java-modules/core-java-security-3/pom.xml +++ b/core-java-modules/core-java-security-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-security-3 - core-java-security-3 jar + core-java-security-3 com.baeldung.core-java-modules @@ -30,11 +30,6 @@ jaxb-api ${jaxb-api.version} - - com.google.guava - guava - ${guava.version} - org.springframework.security spring-security-crypto diff --git a/core-java-modules/core-java-security-4/pom.xml b/core-java-modules/core-java-security-4/pom.xml index 5bbf505079..e59ee0b5eb 100644 --- a/core-java-modules/core-java-security-4/pom.xml +++ b/core-java-modules/core-java-security-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-security-4 - core-java-security-4 jar + core-java-security-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-security-algorithms/README.md b/core-java-modules/core-java-security-algorithms/README.md index a1ce244ab8..c31e859e60 100644 --- a/core-java-modules/core-java-security-algorithms/README.md +++ b/core-java-modules/core-java-security-algorithms/README.md @@ -9,3 +9,4 @@ This module contains articles about core Java Security Algorithms such as AES, D - [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception) - [RSA in Java](https://www.baeldung.com/java-rsa) - [3DES in Java](https://www.baeldung.com/java-3des) +- [Blowfish Encryption Algorithm](https://www.baeldung.com/java-jca-blowfish-implementation) diff --git a/core-java-modules/core-java-security-algorithms/pom.xml b/core-java-modules/core-java-security-algorithms/pom.xml index 0204203fd7..006000565d 100644 --- a/core-java-modules/core-java-security-algorithms/pom.xml +++ b/core-java-modules/core-java-security-algorithms/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-security-algorithms - core-java-security-algorithms jar + core-java-security-algorithms com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/blowfish/BlowFishUnitTest.java b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/blowfish/BlowFishUnitTest.java new file mode 100644 index 0000000000..5b5a3b2055 --- /dev/null +++ b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/blowfish/BlowFishUnitTest.java @@ -0,0 +1,92 @@ +package com.baeldung.blowfish; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class BlowFishUnitTest { + + @Test + public void givenBlowfishAlogrithm_whenEncryptAndDecryptString_thenCompareResults() throws Exception { + String secretMessage = "Secret message to encrypt"; + String secretKey = "MyKey123"; + byte[] keyData = secretKey.getBytes(); + + // Encryption + SecretKeySpec secretKeySpec = new SecretKeySpec(keyData, "Blowfish"); + Cipher encryptCipher = Cipher.getInstance("Blowfish"); + encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + byte[] encryptedBytes = encryptCipher.doFinal(secretMessage.getBytes(StandardCharsets.UTF_8)); + String encryptedtext = Base64.getEncoder().encodeToString(encryptedBytes); + + // Decryption + byte[] ecryptedtexttobytes = Base64.getDecoder().decode(encryptedtext); + Cipher decryptCipher = Cipher.getInstance("Blowfish"); + decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + byte[] decrypted = decryptCipher.doFinal(ecryptedtexttobytes); + String decrypedText = new String(decrypted, StandardCharsets.UTF_8); + + Assertions.assertEquals(secretMessage, decrypedText); + } + + @Test + public void givenBlowfishAlogrithm_whenEncryptAndDecryptFile_thenCompareResults() throws Exception { + String secretKey = "MyKey123"; + byte[] keyData = secretKey.getBytes(); + SecretKeySpec secretKeySpec = new SecretKeySpec(keyData, "Blowfish"); + + String originalContent = "some secret text file"; + Path tempFile = Files.createTempFile("temp", "txt"); + writeFile(tempFile, originalContent); + + // Encryption + byte[] fileBytes = Files.readAllBytes(tempFile); + Cipher encryptCipher = Cipher.getInstance("Blowfish"); + encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes); + try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) { + stream.write(encryptedFileBytes); + } + + // Decryption + encryptedFileBytes = Files.readAllBytes(tempFile); + Cipher decryptCipher = Cipher.getInstance("Blowfish"); + decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes); + try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) { + stream.write(decryptedFileBytes); + } + + String fileContent = readFile(tempFile); + + Assertions.assertEquals(originalContent, fileContent); + } + + private void writeFile(Path path, String content) throws Exception { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + writer.write(content); + } + } + + private String readFile(Path path) throws Exception { + StringBuilder resultStringBuilder = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new FileReader(path.toFile()))) { + String line; + while ((line = br.readLine()) != null) { + resultStringBuilder.append(line); + } + } + return resultStringBuilder.toString(); + } +} diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml index 921017b080..0fd3f37ef1 100644 --- a/core-java-modules/core-java-security/pom.xml +++ b/core-java-modules/core-java-security/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-security - core-java-security jar + core-java-security com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-serialization/pom.xml b/core-java-modules/core-java-serialization/pom.xml index 5989dbf870..51011244b0 100644 --- a/core-java-modules/core-java-serialization/pom.xml +++ b/core-java-modules/core-java-serialization/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-serialization - core-java-serialization jar + core-java-serialization com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams-2/pom.xml b/core-java-modules/core-java-streams-2/pom.xml index d35dfa45b0..d61f94cbaa 100644 --- a/core-java-modules/core-java-streams-2/pom.xml +++ b/core-java-modules/core-java-streams-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-2 - core-java-streams-2 jar + core-java-streams-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams-3/pom.xml b/core-java-modules/core-java-streams-3/pom.xml index 9c657119b5..95b1038653 100644 --- a/core-java-modules/core-java-streams-3/pom.xml +++ b/core-java-modules/core-java-streams-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-3 - core-java-streams-3 jar + core-java-streams-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams-4/pom.xml b/core-java-modules/core-java-streams-4/pom.xml index 79b07d0482..972b47ce80 100644 --- a/core-java-modules/core-java-streams-4/pom.xml +++ b/core-java-modules/core-java-streams-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-4 - core-java-streams-4 jar + core-java-streams-4 com.baeldung.core-java-modules @@ -73,11 +73,6 @@ commons-collections4 ${apache.commons.collection4.version} - - com.google.guava - guava - ${guava.version} - com.oath.cyclops cyclops diff --git a/core-java-modules/core-java-streams-5/pom.xml b/core-java-modules/core-java-streams-5/pom.xml index 3e439145cb..a991043bc2 100644 --- a/core-java-modules/core-java-streams-5/pom.xml +++ b/core-java-modules/core-java-streams-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-5 - core-java-streams-5 jar + core-java-streams-5 com.baeldung.core-java-modules @@ -38,11 +38,7 @@ vavr ${vavr.version} - - com.google.guava - guava - ${guava.version} - + org.apache.commons commons-collections4 diff --git a/core-java-modules/core-java-streams-6/README.md b/core-java-modules/core-java-streams-6/README.md new file mode 100644 index 0000000000..415fa9b991 --- /dev/null +++ b/core-java-modules/core-java-streams-6/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Java 8 Stream Operation on the Empty List](https://www.baeldung.com/java-empty-list-stream-ops) diff --git a/core-java-modules/core-java-streams-6/pom.xml b/core-java-modules/core-java-streams-6/pom.xml index c8cff002e4..5d13429c36 100644 --- a/core-java-modules/core-java-streams-6/pom.xml +++ b/core-java-modules/core-java-streams-6/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-6 - core-java-streams-6 jar + core-java-streams-6 com.baeldung.core-java-modules @@ -43,11 +43,6 @@ vavr ${vavr.version} - - com.google.guava - guava - ${guava.version} - org.apache.commons commons-collections4 diff --git a/core-java-modules/core-java-streams-collect/pom.xml b/core-java-modules/core-java-streams-collect/pom.xml index ce35e66d91..a73789d499 100644 --- a/core-java-modules/core-java-streams-collect/pom.xml +++ b/core-java-modules/core-java-streams-collect/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-collect - core-java-streams-collect jar + core-java-streams-collect com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams-maps/README.md b/core-java-modules/core-java-streams-maps/README.md index 8f311d91a5..0f6796f262 100644 --- a/core-java-modules/core-java-streams-maps/README.md +++ b/core-java-modules/core-java-streams-maps/README.md @@ -1,3 +1,4 @@ ## Relevant Articles: - [Handle Duplicate Keys When Producing Map Using Java Stream](https://www.baeldung.com/java-duplicate-keys-when-producing-map-using-stream) -- [Convert a Stream into a Map or Multimap in Java](https://www.baeldung.com/java-convert-stream-map-multimap) \ No newline at end of file +- [Convert a Stream into a Map or Multimap in Java](https://www.baeldung.com/java-convert-stream-map-multimap) +- [Flatten a Stream of Maps to a Single Map in Java](https://www.baeldung.com/java-flatten-stream-map) diff --git a/core-java-modules/core-java-streams-maps/pom.xml b/core-java-modules/core-java-streams-maps/pom.xml index 0d231728c7..b04780b38b 100644 --- a/core-java-modules/core-java-streams-maps/pom.xml +++ b/core-java-modules/core-java-streams-maps/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-maps - core-java-streams-maps jar + core-java-streams-maps com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java new file mode 100644 index 0000000000..b23dd07fc8 --- /dev/null +++ b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java @@ -0,0 +1,143 @@ +package com.baeldung.streams.mapstreamtomap; + +import static java.lang.Math.max; +import static java.util.stream.Collectors.flatMapping; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.reducing; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +public class MapStreamToMapUnitTest { + + Map playerMap1 = new HashMap() {{ + put("Kai", 92); + put("Liam", 100); + }}; + Map playerMap2 = new HashMap() {{ + put("Eric", 42); + put("Kevin", 77); + }}; + Map playerMap3 = new HashMap() {{ + put("Saajan", 35); + }}; + Map playerMap4 = new HashMap() {{ + put("Kai", 76); + }}; + Map playerMap5 = new HashMap() {{ + put("Kai", null); + put("Jerry", null); + }}; + + @Test + void givenMapsStream_whenUsingFlatMapAndToMap_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); + put("Eric", 42); + put("Kevin", 77); + }}; + + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3) + .flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + assertEquals(expectedMap, mergedMap); + } + + @Test + void givenMapsWithDuplicateKeys_whenUsingFlatMapAndToMap_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 76 and 92 + put("Eric", 42); + put("Kevin", 77); + }}; + + assertThrows(IllegalStateException.class, () -> Stream.of(playerMap1, playerMap2, playerMap3, playerMap4) + .flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)), "Duplicate key Kai (attempted merging values 92 and 76)"); + + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3, playerMap4) + .flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max)); + + assertEquals(expectedMap, mergedMap); + } + + private Integer maxInteger(Integer int1, Integer int2) { + if (int1 == null) { + return int2; + } + if (int2 == null) { + return int1; + } + return max(int1, int2); + } + + @Test + void givenMapsWithDuplicateKeysAndNullValues_whenUsingFlatMapWithForEach_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 92, 76, and null + put("Eric", 42); + put("Kevin", 77); + put("Jerry", null); + }}; + + assertThrows(NullPointerException.class, () -> Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max))); + + Map mergedMap = new HashMap<>(); + Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(map -> map.entrySet() + .stream()) + .forEach(entry -> { + String k = entry.getKey(); + Integer v = entry.getValue(); + if (mergedMap.containsKey(k)) { + mergedMap.put(k, maxInteger(mergedMap.get(k), v)); + } else { + mergedMap.put(k, v); + } + }); + assertEquals(expectedMap, mergedMap); + + } + + @Test + void givenMapsWithDuplicateKeysAndNullValues_whenUsingReduce_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 92, 76, and null + put("Eric", 42); + put("Kevin", 77); + put("Jerry", null); + }}; + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(x -> x.entrySet() + .stream()) + .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, reducing(null, this::maxInteger)))); + assertEquals(expectedMap, mergedMap); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-streams-simple/pom.xml b/core-java-modules/core-java-streams-simple/pom.xml index 30a5b3f568..a3855e20c5 100644 --- a/core-java-modules/core-java-streams-simple/pom.xml +++ b/core-java-modules/core-java-streams-simple/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams-simple - core-java-streams-simple jar + core-java-streams-simple com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-streams/pom.xml b/core-java-modules/core-java-streams/pom.xml index e5e6adf3c0..5e1ad44c10 100644 --- a/core-java-modules/core-java-streams/pom.xml +++ b/core-java-modules/core-java-streams/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-streams - core-java-streams jar + core-java-streams com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-algorithms-2/pom.xml b/core-java-modules/core-java-string-algorithms-2/pom.xml index 3fdb022a4b..65400f017e 100644 --- a/core-java-modules/core-java-string-algorithms-2/pom.xml +++ b/core-java-modules/core-java-string-algorithms-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-algorithms-2 - core-java-string-algorithms-2 jar + core-java-string-algorithms-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml index 9d3b824df4..6e7264dcdd 100644 --- a/core-java-modules/core-java-string-algorithms-3/pom.xml +++ b/core-java-modules/core-java-string-algorithms-3/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-algorithms-3 - core-java-string-algorithms-3 jar + core-java-string-algorithms-3 com.baeldung.core-java-modules @@ -55,7 +55,7 @@ - 1.7 + 1.8.0 5.1.1 1.10.0 diff --git a/core-java-modules/core-java-string-algorithms-4/pom.xml b/core-java-modules/core-java-string-algorithms-4/pom.xml index b374b48743..704c9f4018 100644 --- a/core-java-modules/core-java-string-algorithms-4/pom.xml +++ b/core-java-modules/core-java-string-algorithms-4/pom.xml @@ -3,12 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-algorithms-4 - core-java-string-algorithms-4 jar + core-java-string-algorithms-4 com.baeldung.core-java-modules core-java-modules 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/core-java-modules/core-java-string-algorithms/pom.xml b/core-java-modules/core-java-string-algorithms/pom.xml index 10d28feb2f..1666d64ed3 100644 --- a/core-java-modules/core-java-string-algorithms/pom.xml +++ b/core-java-modules/core-java-string-algorithms/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-algorithms - core-java-string-algorithms jar + core-java-string-algorithms com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-apis-2/pom.xml b/core-java-modules/core-java-string-apis-2/pom.xml index c77ea7c64b..9375b92086 100644 --- a/core-java-modules/core-java-string-apis-2/pom.xml +++ b/core-java-modules/core-java-string-apis-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-apis-2 - core-java-string-apis-2 jar + core-java-string-apis-2 com.baeldung.core-java-modules @@ -14,11 +14,6 @@ - - com.google.guava - guava - ${guava.version} - org.apache.commons commons-lang3 diff --git a/core-java-modules/core-java-string-apis/pom.xml b/core-java-modules/core-java-string-apis/pom.xml index 5d7737228c..743c331ad2 100644 --- a/core-java-modules/core-java-string-apis/pom.xml +++ b/core-java-modules/core-java-string-apis/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-apis - core-java-string-apis jar + core-java-string-apis com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-conversions-2/pom.xml b/core-java-modules/core-java-string-conversions-2/pom.xml index 90463271b8..8a3719dc31 100644 --- a/core-java-modules/core-java-string-conversions-2/pom.xml +++ b/core-java-modules/core-java-string-conversions-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-conversions-2 - core-java-string-conversions-2 jar + core-java-string-conversions-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-conversions-3/README.md b/core-java-modules/core-java-string-conversions-3/README.md index 144773b7c3..5ef055b39b 100644 --- a/core-java-modules/core-java-string-conversions-3/README.md +++ b/core-java-modules/core-java-string-conversions-3/README.md @@ -3,6 +3,6 @@ - [Convert String to Int Using Encapsulation](https://www.baeldung.com/java-encapsulation-convert-string-to-int) - [HashMap with Multiple Values for the Same Key](https://www.baeldung.com/java-hashmap-multiple-values-per-key) - [Split Java String Into Key-Value Pairs](https://www.baeldung.com/java-split-string-map) -- [How to Center Text Output in Java](https://www.baeldung.com/java-center-text-output) - [How to Convert an Object to String](https://www.baeldung.com/java-object-string-representation) - [Convert String to long or Long in Java](https://www.baeldung.com/java-convert-string-long) +- [Convert a String to a List of Characters in Java](https://www.baeldung.com/java-convert-string-list-characters) diff --git a/core-java-modules/core-java-string-conversions-3/pom.xml b/core-java-modules/core-java-string-conversions-3/pom.xml index b494a03fa7..3ff28e7c7c 100644 --- a/core-java-modules/core-java-string-conversions-3/pom.xml +++ b/core-java-modules/core-java-string-conversions-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-conversions-3 - core-java-string-conversions-3 jar + core-java-string-conversions-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-conversions/pom.xml b/core-java-modules/core-java-string-conversions/pom.xml index b87431cd0b..676eec0c65 100644 --- a/core-java-modules/core-java-string-conversions/pom.xml +++ b/core-java-modules/core-java-string-conversions/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-conversions - core-java-string-conversions jar + core-java-string-conversions com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-2/pom.xml b/core-java-modules/core-java-string-operations-2/pom.xml index 76f21aa726..33ace9cb0a 100644 --- a/core-java-modules/core-java-string-operations-2/pom.xml +++ b/core-java-modules/core-java-string-operations-2/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-2 - core-java-string-operations-2 jar + core-java-string-operations-2 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-3/pom.xml b/core-java-modules/core-java-string-operations-3/pom.xml index a82a0d5b11..94fef545e9 100644 --- a/core-java-modules/core-java-string-operations-3/pom.xml +++ b/core-java-modules/core-java-string-operations-3/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-3 - core-java-string-operations-3 jar + core-java-string-operations-3 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-4/pom.xml b/core-java-modules/core-java-string-operations-4/pom.xml index 2537deb48b..a00d03670a 100644 --- a/core-java-modules/core-java-string-operations-4/pom.xml +++ b/core-java-modules/core-java-string-operations-4/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-4 - core-java-string-operations-4 jar + core-java-string-operations-4 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-5/pom.xml b/core-java-modules/core-java-string-operations-5/pom.xml index 768a04ba23..17a3c812ab 100644 --- a/core-java-modules/core-java-string-operations-5/pom.xml +++ b/core-java-modules/core-java-string-operations-5/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-5 - core-java-string-operations-5 jar + core-java-string-operations-5 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-6/pom.xml b/core-java-modules/core-java-string-operations-6/pom.xml index 2cd7c6ad3e..1df0c9a188 100644 --- a/core-java-modules/core-java-string-operations-6/pom.xml +++ b/core-java-modules/core-java-string-operations-6/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-6 - core-java-string-operations-6 jar + core-java-string-operations-6 com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-string-operations-7/pom.xml b/core-java-modules/core-java-string-operations-7/pom.xml index ebc587715d..19d9b39e3f 100644 --- a/core-java-modules/core-java-string-operations-7/pom.xml +++ b/core-java-modules/core-java-string-operations-7/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-7 - core-java-string-operations-7 jar + core-java-string-operations-7 com.baeldung.core-java-modules @@ -50,12 +50,6 @@ 5.8.1 test - - org.liquibase - liquibase-core - ${liquibase.core.version} - test - junit junit @@ -84,7 +78,6 @@ 2.9.1 1.10.0 74.1 - 4.25.0 \ No newline at end of file diff --git a/core-java-modules/core-java-string-operations-8/README.md b/core-java-modules/core-java-string-operations-8/README.md index 01e4cecfd9..018fcdc987 100644 --- a/core-java-modules/core-java-string-operations-8/README.md +++ b/core-java-modules/core-java-string-operations-8/README.md @@ -4,3 +4,8 @@ - [Check if String is Base64 Encoded](https://www.baeldung.com/java-check-string-base64-encoding) - [Find an Unique Email Address in a List](https://www.baeldung.com/java-find-unique-email-address) - [Get First n Characters in a String in Java](https://www.baeldung.com/get-first-n-characters-in-a-string-in-java) +- [Remove Only Trailing Spaces or Whitespace From a String in Java](https://www.baeldung.com/java-string-remove-only-trailing-whitespace) +- [Get the Initials of a Name in Java](https://www.baeldung.com/java-shorten-name-initials) +- [Normalizing the EOL Character in Java](https://www.baeldung.com/java-normalize-end-of-line-character) +- [Converting UTF-8 to ISO-8859-1 in Java](https://www.baeldung.com/java-utf-8-iso-8859-1-conversion) +- [Get Last n Characters From a String](https://www.baeldung.com/java-string-get-last-n-characters) diff --git a/core-java-modules/core-java-string-operations-8/pom.xml b/core-java-modules/core-java-string-operations-8/pom.xml index 4e155a9851..0b6cdc6b2f 100644 --- a/core-java-modules/core-java-string-operations-8/pom.xml +++ b/core-java-modules/core-java-string-operations-8/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations-8 - core-java-string-operations-8 jar + core-java-string-operations-8 com.baeldung.core-java-modules @@ -20,9 +20,10 @@ ${apache.commons.lang3.version} - com.google.guava - guava - ${guava.version} + org.apache.storm + storm-core + 1.2.2 + test diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/EOLNormalizer/EOLNormalizerUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/EOLNormalizer/EOLNormalizerUnitTest.java new file mode 100644 index 0000000000..caeea60da1 --- /dev/null +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/EOLNormalizer/EOLNormalizerUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.EOLNormalizer; + +import org.apache.storm.shade.org.apache.commons.lang.StringUtils; +import org.junit.Test; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +public class EOLNormalizerUnitTest { + String originalText = "This is a text\rwith different\r\nEOL characters\n"; + String expectedText = "This is a text" + System.getProperty("line.separator") + "with different" + System.getProperty("line.separator") + + "EOL characters" + System.getProperty("line.separator"); + + @Test + public void givenText_whenUsingStringReplace_thenEOLNormalized() { + String normalizedText = originalText.replaceAll("\\r\\n|\\r|\\n", System.getProperty("line.separator")); + assertEquals(expectedText, normalizedText); + } + + @Test + public void givenText_whenUsingStringUtils_thenEOLNormalized() { + String normalizedText = StringUtils.replaceEach(originalText, new String[]{"\r\n", "\r", "\n"}, new String[]{System.getProperty("line.separator"), System.getProperty("line.separator"), System.getProperty("line.separator")}); + assertEquals(expectedText, normalizedText); + } + + @Test + public void givenText_whenUsingStreamAPI_thenEOLNormalized() { + String normalizedText = Arrays.stream(originalText.split("\\r\\n|\\r|\\n")) + .collect(Collectors.joining(System.getProperty("line.separator"))).trim(); + assertEquals(expectedText.trim(), normalizedText); + } +} diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java new file mode 100644 index 0000000000..f47ea5fdaf --- /dev/null +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.UTF8ToISO; + +import org.junit.jupiter.api.Test; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; + +import static org.junit.Assert.assertArrayEquals; + +public class UTF8ToISOUnitTest { + String string = "âabcd"; + byte[] expectedBytes = new byte[]{(byte) 0xE2, 0x61, 0x62, 0x63, 0x64}; + + @Test + public void givenUtf8String_whenUsingGetByte_thenIsoBytesShouldBeEqual() { + byte[] iso88591bytes = string.getBytes(StandardCharsets.ISO_8859_1); + assertArrayEquals(expectedBytes, iso88591bytes); + } + + @Test + public void givenString_whenUsingByteBufferCharBufferConvertToIso_thenBytesShouldBeEqual() { + ByteBuffer inputBuffer = ByteBuffer.wrap(string.getBytes(StandardCharsets.UTF_8)); + CharBuffer data = StandardCharsets.UTF_8.decode(inputBuffer); + ByteBuffer outputBuffer = StandardCharsets.ISO_8859_1.encode(data); + byte[] outputData = new byte[outputBuffer.remaining()]; + outputBuffer.get(outputData); + assertArrayEquals(expectedBytes, outputData); + } +} diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java new file mode 100644 index 0000000000..0d30653082 --- /dev/null +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.lastncharacters; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class LastNCharactersUnitTest { + + private String s; + private int n; + + @BeforeEach + void init() { + s = "10-03-2024"; + n = 4; + } + + @Test + void givenString_whenUsingIntStreamAsStreamSource_thenObtainLastNCharacters() { + String result = s.chars() + .mapToObj(c -> (char) c) + .skip(s.length() - n) + .map(String::valueOf) + .collect(Collectors.joining()); + + assertThat(result).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingOneArgSubstringMethod_thenObtainLastNCharacters() { + int beginIndex = s.length() - n; + + assertThat(s.substring(beginIndex)).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingStreamOfCharactersAsSource_thenObtainLastNCharacters() { + String result = Arrays.stream(ArrayUtils.toObject(s.toCharArray())) + .skip(s.length() - n) + .map(String::valueOf) + .collect(Collectors.joining()); + + assertThat(result).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingStringUtilsRight_thenObtainLastNCharacters() { + assertThat(StringUtils.right(s, n)).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingTwoArgSubstringMethod_thenObtainLastNCharacters() { + int beginIndex = s.length() - n; + String result = s.substring(beginIndex, s.length()); + + assertThat(result).isEqualTo("2024"); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-string-operations/pom.xml b/core-java-modules/core-java-string-operations/pom.xml index 7b91600a6b..b34c0081c3 100644 --- a/core-java-modules/core-java-string-operations/pom.xml +++ b/core-java-modules/core-java-string-operations/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-string-operations - core-java-string-operations jar + core-java-string-operations com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-strings/pom.xml b/core-java-modules/core-java-strings/pom.xml index b43e7bfe73..c52d293829 100644 --- a/core-java-modules/core-java-strings/pom.xml +++ b/core-java-modules/core-java-strings/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-strings - core-java-strings jar + core-java-strings com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-sun/pom.xml b/core-java-modules/core-java-sun/pom.xml index 7f1517e246..03a8cff885 100644 --- a/core-java-modules/core-java-sun/pom.xml +++ b/core-java-modules/core-java-sun/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-sun - core-java-sun jar + core-java-sun com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-swing/pom.xml b/core-java-modules/core-java-swing/pom.xml index b46fe0f65a..462e31e439 100644 --- a/core-java-modules/core-java-swing/pom.xml +++ b/core-java-modules/core-java-swing/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-swing - core-java-swing jar + core-java-swing com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-time-measurements/pom.xml b/core-java-modules/core-java-time-measurements/pom.xml index 2dd713efe8..fc45017dcd 100644 --- a/core-java-modules/core-java-time-measurements/pom.xml +++ b/core-java-modules/core-java-time-measurements/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-time-measurements - core-java-time-measurements jar + core-java-time-measurements com.baeldung.core-java-modules diff --git a/core-java-modules/core-java-uuid/pom.xml b/core-java-modules/core-java-uuid/pom.xml index 76154033c2..4ecb42952d 100644 --- a/core-java-modules/core-java-uuid/pom.xml +++ b/core-java-modules/core-java-uuid/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-uuid - core-java-uuid jar + core-java-uuid com.baeldung.core-java-modules diff --git a/core-java-modules/java-rmi/pom.xml b/core-java-modules/java-rmi/pom.xml index aa864b49c7..6d6593bb0b 100644 --- a/core-java-modules/java-rmi/pom.xml +++ b/core-java-modules/java-rmi/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.rmi java-rmi - java-rmi jar + java-rmi com.baeldung.core-java-modules diff --git a/core-java-modules/java-spi/exchange-rate-api/pom.xml b/core-java-modules/java-spi/exchange-rate-api/pom.xml index bb22c63de1..9e8abbc873 100644 --- a/core-java-modules/java-spi/exchange-rate-api/pom.xml +++ b/core-java-modules/java-spi/exchange-rate-api/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung exchange-rate-api - exchange-rate-api jar + exchange-rate-api com.baeldung diff --git a/core-java-modules/java-spi/exchange-rate-app/pom.xml b/core-java-modules/java-spi/exchange-rate-app/pom.xml index fbf87eb026..8b8e7f9c42 100644 --- a/core-java-modules/java-spi/exchange-rate-app/pom.xml +++ b/core-java-modules/java-spi/exchange-rate-app/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 exchange-rate-app - exchange-rate-app jar + exchange-rate-app com.baeldung diff --git a/core-java-modules/java-spi/exchange-rate-impl/pom.xml b/core-java-modules/java-spi/exchange-rate-impl/pom.xml index 7824bbc9e5..8a1c320dd9 100644 --- a/core-java-modules/java-spi/exchange-rate-impl/pom.xml +++ b/core-java-modules/java-spi/exchange-rate-impl/pom.xml @@ -5,8 +5,8 @@ 4.0.0 exchange-rate-impl com.baeldung - exchange-rate-impl jar + exchange-rate-impl com.baeldung diff --git a/core-java-modules/java-spi/pom.xml b/core-java-modules/java-spi/pom.xml index 837700103e..97aee9838f 100644 --- a/core-java-modules/java-spi/pom.xml +++ b/core-java-modules/java-spi/pom.xml @@ -5,9 +5,9 @@ 4.0.0 com.baeldung java-spi - java-spi 1.0.0-SNAPSHOT pom + java-spi com.baeldung.core-java-modules diff --git a/core-java-modules/java-websocket/pom.xml b/core-java-modules/java-websocket/pom.xml index 8d8e57b765..616f633960 100644 --- a/core-java-modules/java-websocket/pom.xml +++ b/core-java-modules/java-websocket/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 java-websocket - java-websocket war + java-websocket com.baeldung.core-java-modules diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 3d26d51a6a..bd7aae6410 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -5,9 +5,9 @@ 4.0.0 com.baeldung.core-java-modules core-java-modules - core-java-modules 0.0.1-SNAPSHOT pom + core-java-modules com.baeldung @@ -99,6 +99,7 @@ core-java-collections-maps-2 core-java-collections-maps-3 core-java-collections-maps-7 + core-java-collections-maps-8 core-java-compiler core-java-concurrency-2 core-java-concurrency-advanced @@ -144,6 +145,7 @@ core-java-lang-6 core-java-lang-math core-java-lang-math-2 + core-java-lang-math-4 core-java-lang-oop-constructors core-java-lang-oop-patterns core-java-lang-oop-generics @@ -243,6 +245,7 @@ 17 17 + 20240303 diff --git a/custom-pmd/pom.xml b/custom-pmd/pom.xml index 115ba7565c..1b5c3e6238 100644 --- a/custom-pmd/pom.xml +++ b/custom-pmd/pom.xml @@ -6,8 +6,8 @@ com.baeldung.pmd custom-pmd 0.0.1 - custom-pmd jar + custom-pmd com.baeldung diff --git a/deeplearning4j/pom.xml b/deeplearning4j/pom.xml index deb5b34a39..bad7e8ecc1 100644 --- a/deeplearning4j/pom.xml +++ b/deeplearning4j/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 deeplearning4j - deeplearning4j jar + deeplearning4j com.baeldung diff --git a/di-modules/guice/pom.xml b/di-modules/guice/pom.xml index d0d2876fc8..115bae5e7b 100644 --- a/di-modules/guice/pom.xml +++ b/di-modules/guice/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 guice - guice jar + guice com.baeldung diff --git a/di-modules/pom.xml b/di-modules/pom.xml index 984180cb28..b07d436867 100644 --- a/di-modules/pom.xml +++ b/di-modules/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 di-modules - di-modules pom + di-modules parent-modules diff --git a/disruptor/pom.xml b/disruptor/pom.xml index b3b065d67e..942eb83e7c 100644 --- a/disruptor/pom.xml +++ b/disruptor/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 disruptor - disruptor jar + disruptor com.baeldung diff --git a/docker-modules/docker-caching/README.md b/docker-modules/docker-caching/README.md deleted file mode 100644 index d985210683..0000000000 --- a/docker-modules/docker-caching/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant Articles: - -- [Caching Maven Dependencies with Docker](https://www.baeldung.com/ops/docker-cache-maven-dependencies) diff --git a/docker-modules/docker-caching/multi-module-caching/Dockerfile b/docker-modules/docker-caching/multi-module-caching/Dockerfile deleted file mode 100644 index 96ebe2a76b..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME - -ADD pom.xml $HOME -ADD core/pom.xml $HOME/core/pom.xml -ADD runner/pom.xml $HOME/runner/pom.xml - -RUN mvn -pl core verify --fail-never -ADD core $HOME/core -RUN mvn -pl core install -RUN mvn -pl runner verify --fail-never -ADD runner $HOME/runner -RUN mvn -pl core,runner package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/runner/target/runner-0.0.1-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit b/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit deleted file mode 100644 index e89ce38e4b..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME - -ADD . $HOME -RUN --mount=type=cache,target=/root/.m2 mvn -f $HOME/pom.xml clean package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/runner/target/runner-0.0.1-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml b/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml deleted file mode 100644 index 991162ddfa..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - core-module - - - multi-module-caching - com.baeldung - 0.0.1-SNAPSHOT - - - - - com.google.guava - guava - ${guava.version} - - - - - 8 - 8 - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java b/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java deleted file mode 100644 index d8c73a331a..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.maven_caching; - -import com.google.common.io.Files; - -public class CoreClass { - - public String method() { - return "Hello from core module!!"; - } - - public String dependencyMethod() { - return Files.simplifyPath("/home/app/test"); - } -} diff --git a/docker-modules/docker-caching/multi-module-caching/pom.xml b/docker-modules/docker-caching/multi-module-caching/pom.xml deleted file mode 100644 index b9977f8f3a..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - 4.0.0 - com.baeldung - multi-module-caching - 0.0.1-SNAPSHOT - Multi-module Maven caching example - pom - - - runner-module - core-module - - - - - - com.google.guava - guava - ${guava.version} - - - - - - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml b/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml deleted file mode 100644 index e608706864..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - runner-module - - - multi-module-caching - com.baeldung - 0.0.1-SNAPSHOT - - - - - com.baeldung - core-module - 0.0.1-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - jar-with-dependencies - - - - true - com.baeldung.maven_caching.MavenCachingApplication - - - - - - assemble-all - package - - single - - - - - - - - - 8 - 8 - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java b/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java deleted file mode 100644 index 3673dd86c1..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.maven_caching; - -public class MavenCachingApplication { - - public static void main(String[] args) { - CoreClass cc = new CoreClass(); - System.out.println(cc.method()); - System.out.println(cc.dependencyMethod()); - } - -} diff --git a/docker-modules/docker-caching/single-module-caching/Dockerfile b/docker-modules/docker-caching/single-module-caching/Dockerfile deleted file mode 100644 index 02157c0dd6..0000000000 --- a/docker-modules/docker-caching/single-module-caching/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME -ADD pom.xml $HOME -RUN mvn verify --fail-never - -ADD . $HOME -RUN mvn package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/target/single-module-caching-1.0-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit b/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit deleted file mode 100644 index 29384ce208..0000000000 --- a/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME -ADD . $HOME - -RUN --mount=type=cache,target=/root/.m2 mvn -f $HOME/pom.xml clean package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/target/single-module-caching-1.0-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/pom.xml b/docker-modules/docker-caching/single-module-caching/pom.xml deleted file mode 100644 index 1e90c7130e..0000000000 --- a/docker-modules/docker-caching/single-module-caching/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - com.baeldung - single-module-caching - 1.0-SNAPSHOT - - - - com.google.guava - guava - ${guava.version} - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - jar-with-dependencies - - - - true - com.baeldung.maven_caching.MavenCachingMain - - - - - - assemble-all - package - - single - - - - - - - - - 8 - 8 - UTF-8 - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java b/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java deleted file mode 100644 index 4fbd8e5311..0000000000 --- a/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.maven_caching; - -import com.google.common.io.Files; - -public class MavenCachingMain { - - public static void main(String[] args) { - System.out.println("Hello from maven_caching app!!!"); - System.out.println(Files.simplifyPath("/home/app/test")); - } -} diff --git a/docker-modules/docker-compose-2/README.md b/docker-modules/docker-compose-2/README.md deleted file mode 100644 index 353b85f154..0000000000 --- a/docker-modules/docker-compose-2/README.md +++ /dev/null @@ -1,2 +0,0 @@ -## Relevant Articles: -- [Communicating With Docker Containers on the Same Machine](https://www.baeldung.com/ops/docker-communicating-with-containers-on-same-machine) diff --git a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile b/docker-modules/docker-compose-2/communication_same_machine/Dockerfile deleted file mode 100644 index a0c4ebe59a..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM alpine:latest -MAINTAINER baeldung.com -RUN apk update && apk add iputils && apk add bash && apk add curl \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node b/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node deleted file mode 100644 index 6d8f0eff81..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:8.16.1-alpine -WORKDIR /app -COPY host_docker_internal/package.json /app -COPY host_docker_internal/index.js /app -RUN npm install -CMD node index.js -EXPOSE 8080 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml deleted file mode 100644 index 0a06993241..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - image: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - tty: true - ports: - - 8081:8081 - - alpine-app-2: - container_name: alpine-app-2 - image: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - tty: true - ports: - - 8080:8080 diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml deleted file mode 100644 index 8e7174a9a1..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml +++ /dev/null @@ -1,29 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - extra_hosts: # for linux hosts since version 20.10 - - host.docker.internal:host-gateway - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - networks: - - first-network - - node-app: - container_name: node-app - build: - context: .. - dockerfile: Dockerfile.node - image: node-app - ports: - - 8080:8080 - networks: - - second-network - -networks: - first-network: - driver: bridge - second-network: - driver: bridge \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js deleted file mode 100644 index cefae028e5..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js +++ /dev/null @@ -1,10 +0,0 @@ -var express = require('express') -var app = express() - -app.get('/', function (req, res) { - res.send('Hello World!') -}) - -app.listen(8080, function () { - console.log('app listening on port 8080!') -}) \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json deleted file mode 100644 index cde98b1cfd..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "host_docker_internal", - "version": "1.0.0", - "description": "node js app", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Baeldung", - "license": "ISC", - "dependencies": { - "express": "^4.18.2" - } -} diff --git a/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml deleted file mode 100644 index 0193bd72fb..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml +++ /dev/null @@ -1,34 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - ports: - - 8080:8080 - networks: - network-example: - ipv4_address: 10.5.0.2 - - alpine-app-2: - container_name: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-2 - tty: true - ports: - - 8081:8081 - networks: - network-example: - ipv4_address: 10.5.0.3 - -networks: - network-example: - driver: bridge - ipam: - config: - - subnet: 10.5.0.0/16 - gateway: 10.5.0.1 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml deleted file mode 100644 index cef1a0b5cb..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml +++ /dev/null @@ -1,36 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - ports: - - 8080:8080 - networks: - network-example: - ipv4_address: 192.168.2.2 - - alpine-app-2: - container_name: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-2 - tty: true - ports: - - 8081:8081 - networks: - network-example: - ipv4_address: 192.168.2.3 - -networks: - network-example: - driver: macvlan - driver_opts: - parent: enp0s3 - ipam: - config: - - subnet: 192.168.2.0/24 - gateway: 192.168.2.1 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/pom.xml b/docker-modules/docker-compose-2/pom.xml deleted file mode 100644 index f7f01dc482..0000000000 --- a/docker-modules/docker-compose-2/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - docker-compose-2 - Demo project for Spring Boot and Docker - Module docker-compose-2 - pom - - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 - - - \ No newline at end of file diff --git a/docker-modules/docker-compose/Dockerfile b/docker-modules/docker-compose/Dockerfile deleted file mode 100644 index 382e1d3442..0000000000 --- a/docker-modules/docker-compose/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM openjdk:17-alpine -MAINTAINER baeldung.com -COPY target/docker-compose-0.0.1-SNAPSHOT.jar app.jar -ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/docker-modules/docker-compose/README.md b/docker-modules/docker-compose/README.md deleted file mode 100644 index 4631630e6a..0000000000 --- a/docker-modules/docker-compose/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## Relevant Articles: - -- [Introduction to Docker Compose](https://www.baeldung.com/ops/docker-compose) -- [How to Get Docker-Compose to Always Use the Latest Image](https://www.baeldung.com/ops/docker-compose-latest-image) -- [Communication Between Multiple Docker Compose Projects](https://www.baeldung.com/ops/docker-compose-communication) -- [Difference Between links and depends_on in Docker Compose](https://www.baeldung.com/ops/docker-compose-links-depends-on) -- [Mounting Multiple Volumes on a Docker Container](https://www.baeldung.com/ops/docker-mounting-multiple-volumes) -- [Rebuild Docker Container in Docker Compose](https://www.baeldung.com/rebuild-docker-container-compose) -- [Assign Static IP to Docker Container and Docker-Compose](https://www.baeldung.com/ops/docker-assign-static-ip-container) -- [Exclude a Sub-Folder When Adding a Volume to Docker](https://www.baeldung.com/ops/docker-exclude-sub-folder-when-adding-volume) diff --git a/docker-modules/docker-compose/assign-static-ip/docker-compose.yml b/docker-modules/docker-compose/assign-static-ip/docker-compose.yml deleted file mode 100644 index 9f555d1ad4..0000000000 --- a/docker-modules/docker-compose/assign-static-ip/docker-compose.yml +++ /dev/null @@ -1,27 +0,0 @@ -services: - db: - container_name: mysql_db - image: mysql:latest - environment: - - MYSQL_ROOT_PASSWORD=password - - MYSQL_ROOT_HOST=10.5.0.1 - ports: - - '3306:3306' - volumes: - - db:/var/lib/mysql - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - networks: - network: - ipv4_address: 10.5.0.5 - -volumes: - db: - driver: local - -networks: - network: - driver: bridge - ipam: - config: - - subnet: 10.5.0.0/16 - gateway: 10.5.0.1 \ No newline at end of file diff --git a/docker-modules/docker-compose/assign-static-ip/init.sql b/docker-modules/docker-compose/assign-static-ip/init.sql deleted file mode 100644 index e150bda7c8..0000000000 --- a/docker-modules/docker-compose/assign-static-ip/init.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE DATABASE IF NOT EXISTS test; -CREATE USER 'db_user'@'10.5.0.1' IDENTIFIED BY 'password'; -GRANT ALL PRIVILEGES ON *.* TO 'db_user'@'10.5.0.1' WITH GRANT OPTION; -FLUSH PRIVILEGES; - -use test; - -CREATE TABLE IF NOT EXISTS TEST_TABLE (id int, name varchar(255)); - - -INSERT INTO TEST_TABLE VALUES (1, 'TEST_1'); -INSERT INTO TEST_TABLE VALUES (2, 'TEST_2'); -INSERT INTO TEST_TABLE VALUES (3, 'TEST_3'); \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml deleted file mode 100644 index 1f9b42384e..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - db: - image: postgres:latest - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - web-app: - image: web-app:latest - ports: - - 8080:8080 - depends_on: - - db \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml deleted file mode 100644 index cf84970b3c..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - db: - image: postgres:latest - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - web-app: - image: web-app:latest - ports: - - 8080:8080 - links: - - db \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml deleted file mode 100644 index 6b6796b43d..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml +++ /dev/null @@ -1,36 +0,0 @@ -services: - db: - image: postgres:latest - restart: always - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - volumes: - - db:/var/lib/postgresql/data - networks: - - mynet - - web-app: - image: web-app:latest - depends_on: - - db - networks: - - mynet - ports: - - 8080:8080 - environment: - DB_HOST: db - DB_PORT: 5432 - DB_USER: postgres - DB_PASSWORD: postgres - DB_NAME: postgres - -networks: - mynet: - driver: bridge - -volumes: - db: - driver: local diff --git a/docker-modules/docker-compose/exclude-subfolders/Dockerfile b/docker-modules/docker-compose/exclude-subfolders/Dockerfile deleted file mode 100644 index 9aa1c4ea44..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:12.18.1 -ENV NODE_ENV=production -WORKDIR /app -COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --production -COPY . . -CMD [ "node", "server.js" ] \ No newline at end of file diff --git a/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml b/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml deleted file mode 100644 index 51e536ae5c..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -services: - node-app: - build: . - ports: - - 8080:8080 - volumes: - - .:/app - - my-vol:/app/node_modules/ - -volumes: - my-vol: - driver: local \ No newline at end of file diff --git a/docker-modules/docker-compose/exclude-subfolders/package.json b/docker-modules/docker-compose/exclude-subfolders/package.json deleted file mode 100644 index 118fb33610..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "app", - "version": "1.0.0", - "description": "", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "ronin-mocks": "^0.1.11", - "ronin-server": "^0.1.3" - } -} diff --git a/docker-modules/docker-compose/exclude-subfolders/server.js b/docker-modules/docker-compose/exclude-subfolders/server.js deleted file mode 100644 index 2ad342e4d4..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/server.js +++ /dev/null @@ -1,7 +0,0 @@ -const ronin = require('ronin-server') -const mocks = require('ronin-mocks') - -const server = ronin.server() - -server.use('/', mocks.server(server.Router(), false, true)) -server.start() \ No newline at end of file diff --git a/docker-modules/docker-compose/intro/docker-compose.yml b/docker-modules/docker-compose/intro/docker-compose.yml deleted file mode 100644 index 72d07d6392..0000000000 --- a/docker-modules/docker-compose/intro/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: '3' - -services: - -## VOLUME CONTAINER-TO-CONTAINER AND HOST-TO-CONTAINER TEST ## - - volumes-example-service: - image: alpine:latest - container_name: volumes-example-service - volumes: - - /tmp:/my-volumes/host-volume - - /home:/my-volumes/readonly-host-volume:ro - - my-named-global-volume:/my-volumes/named-global-volume - tty: true # Needed to keep the container running - - another-volumes-example-service: - image: alpine:latest - container_name: another-volumes-example-service - volumes: - - my-named-global-volume:/another-path/the-same-named-global-volume - tty: true # Needed to keep the container running - -## NETWORK CONTAINER-TO-CONTAINER TEST ## - - network-example-service: - image: karthequian/helloworld:latest - container_name: network-example-service - networks: - - my-shared-network - - another-service-in-the-same-network: - image: alpine:latest - container_name: another-service-in-the-same-network - networks: - - my-shared-network - - tty: true # Needed to keep the container running - - another-service-in-its-own-network: - image: alpine:latest - container_name: another-service-in-its-own-network - networks: - - my-private-network - tty: true # Needed to keep the container running - -## NETWORK HOST-TO-CONTAINER TEST ## - - network-example-service-available-to-host-on-port-1337: - image: karthequian/helloworld:latest - container_name: network-example-service-available-to-host-on-port-1337 - networks: - - my-shared-network - ports: - - "1337:80" - -volumes: - my-named-global-volume: - -networks: - my-shared-network: {} - my-private-network: {} diff --git a/docker-modules/docker-compose/latest-image/Dockerfile b/docker-modules/docker-compose/latest-image/Dockerfile deleted file mode 100644 index 71fc1a29d9..0000000000 --- a/docker-modules/docker-compose/latest-image/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM openjdk:11 -COPY target/docker-sample-app-0.0.1.jar app.jar -ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml b/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml deleted file mode 100644 index 27c1d8ee44..0000000000 --- a/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: '2.4' -services: - db: - image: postgres - my_app: - build: . - ports: - - "8080:8080" diff --git a/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml b/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml deleted file mode 100644 index 9a8822f762..0000000000 --- a/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: '2.4' -services: - db: - image: postgres - my_app: - image: "eugen/test-app:latest" - ports: - - "8080:8080" - diff --git a/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml b/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml deleted file mode 100644 index 1a8ea2dc25..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - mysql-db: - image: mysql:latest - environment: - - MYSQL_ROOT_PASSWORD=password - - MYSQL_ROOT_HOST=localhost - ports: - - '3306:3306' - volumes: - - first-volume-data:/var/lib/mysql - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - -volumes: - first-volume-data: - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/init.sql b/docker-modules/docker-compose/multiple-mounts/init.sql deleted file mode 100644 index 345a9914fb..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/init.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE DATABASE IF NOT EXISTS test; - -use test; - -CREATE TABLE IF NOT EXISTS test_table (id int, description varchar(255)); - -INSERT INTO test_table VALUES (1, 'TEST_1'); -INSERT INTO test_table VALUES (2, 'TEST_2'); -INSERT INTO test_table VALUES (3, 'TEST_3'); \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml b/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml deleted file mode 100644 index 98c0275583..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - localstack: - privileged: true - image: localstack/localstack:latest - container_name: localstack - ports: - - '4563-4599:4563-4599' - - '8055:8080' - environment: - - SERVICES=s3 - - DEBUG=1 - - DATA_DIR=/tmp/localstack/data - volumes: - - './.localstack:/var/lib/localstack' - - '/var/run/docker.sock:/var/run/docker.sock' \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml b/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml deleted file mode 100644 index bd722ac5b5..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml +++ /dev/null @@ -1,15 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - volumes: - - first-volume-data:/container-path-1 - - second-volume-data:/container-path-2:ro - -volumes: - first-volume-data: - driver: local - second-volume-data: - driver: local \ No newline at end of file diff --git a/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml b/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml deleted file mode 100644 index edf0934bc9..0000000000 --- a/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: "3.9" -services: - ubuntu: - image: "ubuntu:latest" - tty: true - alpine: - image: "alpine:latest" - tty: true \ No newline at end of file diff --git a/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml b/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml deleted file mode 100644 index 49852dbd78..0000000000 --- a/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: "3.9" -services: - ubuntu: - image: "ubuntu:latest" - tty: true - depends_on: - - "alpine" - alpine: - image: "alpine:latest" - tty: true \ No newline at end of file diff --git a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java b/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java deleted file mode 100644 index d46c57e606..0000000000 --- a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker.app.endpoint; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class MyController { - - @GetMapping - public String version() { - return "1.7"; - } -} diff --git a/docker-modules/docker-compose/src/main/resources/application.properties b/docker-modules/docker-compose/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/docker-modules/docker-compose/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java b/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java deleted file mode 100644 index 7220766988..0000000000 --- a/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker.app; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DockAppApplicationUnitTest { - - @Test - void contextLoads() { - } - -} diff --git a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml deleted file mode 100644 index 42e9eec8a1..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - networks: - - my-app - -networks: - my-app: - name: redis_network - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml deleted file mode 100644 index ef9573a803..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -services: - redis: - image: redis:latest - container_name: redis - ports: - - '6379:6379' - networks: - - network - -networks: - network: - driver: bridge - name: redis_network diff --git a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml deleted file mode 100644 index f3310108ce..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - networks: - - network-example - -networks: - network-example: - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml deleted file mode 100644 index 2cf44a05d6..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - redis: - image: redis:latest - container_name: redis - ports: - - '6379:6379' - networks: - - network-example - -networks: - network-example: - external: true diff --git a/docker-modules/docker-containers/README.md b/docker-modules/docker-containers/README.md index aa5167cc16..a16de50d8d 100644 --- a/docker-modules/docker-containers/README.md +++ b/docker-modules/docker-containers/README.md @@ -1,3 +1,3 @@ ### Relevant Articles: -- [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/ops/docker-jvm-heap-size) +- [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/java-docker-jvm-heap-size) diff --git a/docker-modules/docker-environment-variables/Dockerfile b/docker-modules/docker-environment-variables/Dockerfile deleted file mode 100644 index dcf69ec2cd..0000000000 --- a/docker-modules/docker-environment-variables/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM alpine:latest - -ARG name -ENV env_name $name - -COPY greetings.sh . - -RUN chmod +x /greetings.sh - -CMD ["/greetings.sh"] \ No newline at end of file diff --git a/docker-modules/docker-environment-variables/README.md b/docker-modules/docker-environment-variables/README.md deleted file mode 100644 index 12da2931a3..0000000000 --- a/docker-modules/docker-environment-variables/README.md +++ /dev/null @@ -1,3 +0,0 @@ - -## Relevant Articles: -- [How to Pass Environment Variable Value into Dockerfile](https://www.baeldung.com/ops/dockerfile-env-variable) diff --git a/docker-modules/docker-environment-variables/greetings.sh b/docker-modules/docker-environment-variables/greetings.sh deleted file mode 100644 index 6b9cd61105..0000000000 --- a/docker-modules/docker-environment-variables/greetings.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo Hello $env_name \ No newline at end of file diff --git a/docker-modules/docker-images/.gitignore b/docker-modules/docker-images/.gitignore deleted file mode 100644 index 549e00a2a9..0000000000 --- a/docker-modules/docker-images/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/docker-modules/docker-images/README.md b/docker-modules/docker-images/README.md deleted file mode 100644 index 9ad9f6a3df..0000000000 --- a/docker-modules/docker-images/README.md +++ /dev/null @@ -1,7 +0,0 @@ -### Relevant Articles: - -- [Pushing a Docker Image to a Private Repository](https://www.baeldung.com/ops/docker-push-image-to-private-repository) -- [How to Include Files Outside of Docker’s Build Context](https://www.baeldung.com/ops/docker-include-files-outside-build-context) -- [Adding a Comment in a Dockerfile](https://www.baeldung.com/ops/docker-dockerfile-comments) -- [Updating PATH Environment Variable in Dockerfile](https://www.baeldung.com/ops/dockerfile-path-environment-variable) -- [Keep Subdirectory Structure in Dockerfile Copy](https://www.baeldung.com/ops/dockerfile-copy-same-subdirectory-structure) diff --git a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from b/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from deleted file mode 100644 index 2de102e20d..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest # Declare parent image -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run b/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run deleted file mode 100644 index 186db7683c..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' # Print sentence \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-base b/docker-modules/docker-images/comments/Dockerfile-base deleted file mode 100644 index a25c52b8da..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-base +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-multi-line-comments b/docker-modules/docker-images/comments/Dockerfile-multi-line-comments deleted file mode 100644 index 7c1fc43d34..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-multi-line-comments +++ /dev/null @@ -1,4 +0,0 @@ -# This file is a demonstration -# For a Baeldung article -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-parser-directives b/docker-modules/docker-images/comments/Dockerfile-parser-directives deleted file mode 100644 index e8341b6cec..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-parser-directives +++ /dev/null @@ -1,4 +0,0 @@ -# escape=` -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial&' ` - && echo 'Print more stuff' diff --git a/docker-modules/docker-images/comments/Dockerfile-single-line-comments b/docker-modules/docker-images/comments/Dockerfile-single-line-comments deleted file mode 100644 index a7581769aa..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-single-line-comments +++ /dev/null @@ -1,4 +0,0 @@ -# Declare parent image -FROM ubuntu:latest -# Print sentence -RUN echo 'This is a Baeldung tutorial' diff --git a/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile b/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile deleted file mode 100644 index 754f9f9be3..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM nginx:latest -COPY nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf b/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf deleted file mode 100644 index 944da2f112..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf +++ /dev/null @@ -1,8 +0,0 @@ -events {} - -http { - server { - listen 80; - index index.html; - } -} diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile deleted file mode 100644 index bda0bbe257..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest -COPY sample-site/html/* /etc/nginx/html/ -COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base deleted file mode 100644 index 1b72414bc0..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base +++ /dev/null @@ -1,2 +0,0 @@ -FROM sample-site-base:latest -COPY html/* /etc/nginx/html/ diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script deleted file mode 100644 index 572028f19f..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest -COPY html/* /etc/nginx/html/ -COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh deleted file mode 100644 index e84687b7b7..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh +++ /dev/null @@ -1,6 +0,0 @@ -mkdir tmp-context -cp -R ../html tmp-context/ -cp -R ../../config tmp-context/ -cp Dockerfile-script tmp-context/Dockerfile -docker build -t sample-site:latest tmp-context -rm -rf tmp-context diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html b/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html deleted file mode 100644 index 85f287fad7..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Sample Site - - -

Welcome to the first page of the site

- - diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime deleted file mode 100644 index 3d6436aaa5..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime +++ /dev/null @@ -1,3 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ folder2/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory deleted file mode 100644 index 364c82eb5d..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory +++ /dev/null @@ -1,3 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory deleted file mode 100644 index 16427d90fc..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ /workdir/ -RUN ls --recursive /workdir/ -COPY folder2/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/pom.xml b/docker-modules/docker-images/pom.xml deleted file mode 100644 index eb488f4642..0000000000 --- a/docker-modules/docker-images/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - docker-images - Example application to showcase Docker images features - - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/docker-modules/docker-images/private-repo/Dockerfile b/docker-modules/docker-images/private-repo/Dockerfile deleted file mode 100644 index 99d3c95a26..0000000000 --- a/docker-modules/docker-images/private-repo/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM openjdk:17-jdk-alpine -ARG JAR_FILE=target/*.jar -COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java b/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java deleted file mode 100644 index f7ade95075..0000000000 --- a/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.docker.controllers; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class HelloWorldController { - @GetMapping("/helloworld") - String helloWorld() { - return "Hello World!"; - } -} \ No newline at end of file diff --git a/docker-modules/docker-images/src/main/resources/application.properties b/docker-modules/docker-images/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/docker-modules/docker-images/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docker-modules/docker-images/update-path/Dockerfile-bashrc b/docker-modules/docker-images/update-path/Dockerfile-bashrc deleted file mode 100644 index 4ac110e16b..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-bashrc +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -RUN echo "export PATH=$PATH:/etc/profile" >> ~/.bashrc -RUN cat ~/.bashrc -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/docker-images/update-path/Dockerfile-env b/docker-modules/docker-images/update-path/Dockerfile-env deleted file mode 100644 index 744fba15ed..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-env +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -ENV PATH="$PATH:/etc/profile" -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/docker-images/update-path/Dockerfile-run b/docker-modules/docker-images/update-path/Dockerfile-run deleted file mode 100644 index 1e97f66965..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-run +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -RUN export PATH="$PATH:/etc/profile"; echo $PATH -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/dockerfile-git-strategies/.gitmodules b/docker-modules/dockerfile-git-strategies/.gitmodules deleted file mode 100644 index aa3911dfc3..0000000000 --- a/docker-modules/dockerfile-git-strategies/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "project"] - path = project - url = https://github.com/eugenp/tutorials.git - branch = master \ No newline at end of file diff --git a/docker-modules/dockerfile-git-strategies/Dockerfile b/docker-modules/dockerfile-git-strategies/Dockerfile deleted file mode 100644 index 98911bdcbd..0000000000 --- a/docker-modules/dockerfile-git-strategies/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -ADD git-strategies /project/ -ADD /build/ /project/ -ADD /output/project.jar /project/ - -ADD ssh-private-key /root/.ssh/id_rsa -RUN git clone git@github.com:eugenp/tutorials.git - -ARG username=$GIT_USERNAME -ARG password=$GIT_PASSWORD -RUN git clone https://username:password@github.com:eugenp/tutorials.git - -VOLUME /build/ /project/ - diff --git a/docker-modules/dockerfile-git-strategies/README.md b/docker-modules/dockerfile-git-strategies/README.md deleted file mode 100644 index 7e27328678..0000000000 --- a/docker-modules/dockerfile-git-strategies/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant Articles: - -- [Dockerfile Strategies for Git](https://www.baeldung.com/ops/dockerfile-git-strategies) diff --git a/docker-modules/kaniko/README.md b/docker-modules/kaniko/README.md deleted file mode 100644 index a69a3cb683..0000000000 --- a/docker-modules/kaniko/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [An Introduction to Kaniko](https://www.baeldung.com/ops/kaniko) diff --git a/docker-modules/kaniko/dockerfile b/docker-modules/kaniko/dockerfile deleted file mode 100644 index 0290bf16ed..0000000000 --- a/docker-modules/kaniko/dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu -ENTRYPOINT ["/bin/bash", "-c", "echo hello"] diff --git a/docker-modules/kaniko/pod.yaml b/docker-modules/kaniko/pod.yaml deleted file mode 100644 index 17f9a81b6d..0000000000 --- a/docker-modules/kaniko/pod.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: kaniko -spec: - containers: - - name: kaniko - image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=/workspace/dockerfile", - "--context=dir://workspace", - "--no-push"] - volumeMounts: - - name: dockerfile-storage - mountPath: /workspace - restartPolicy: Never - volumes: - - name: dockerfile-storage - persistentVolumeClaim: - claimName: dockerfile-claim diff --git a/docker-modules/kaniko/volume-claim.yaml b/docker-modules/kaniko/volume-claim.yaml deleted file mode 100644 index 7a1abbf05c..0000000000 --- a/docker-modules/kaniko/volume-claim.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: dockerfile-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: local-storage diff --git a/docker-modules/kaniko/volume.yaml b/docker-modules/kaniko/volume.yaml deleted file mode 100644 index e44663ec5a..0000000000 --- a/docker-modules/kaniko/volume.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: dockerfile - labels: - type: local -spec: - capacity: - storage: 10Gi - accessModes: - - ReadWriteOnce - storageClassName: local-storage - hostPath: - path: /home/docker/kaniko # Path to the local mount directory that was setup diff --git a/docker-modules/pom.xml b/docker-modules/pom.xml index bf35ef23ab..422b65023c 100644 --- a/docker-modules/pom.xml +++ b/docker-modules/pom.xml @@ -14,16 +14,11 @@
- docker-caching - docker-compose - docker-compose-2 docker-containers - docker-images docker-spring-boot docker-spring-boot-postgres docker-java-jar jib - \ No newline at end of file diff --git a/dozer/README.md b/dozer/README.md deleted file mode 100644 index e87e889ce3..0000000000 --- a/dozer/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Dozer - -This module contains articles about Dozer - -### Relevant Articles: - -- [A Guide to Mapping With Dozer](https://www.baeldung.com/dozer) diff --git a/dozer/pom.xml b/dozer/pom.xml deleted file mode 100644 index 66f4ee8227..0000000000 --- a/dozer/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - dozer - dozer - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - net.sf.dozer - dozer - ${dozer.version} - - - - - 5.5.1 - - - \ No newline at end of file diff --git a/drools/pom.xml b/drools/pom.xml index 12aaf1318a..cb4f20d397 100644 --- a/drools/pom.xml +++ b/drools/pom.xml @@ -16,50 +16,50 @@ org.apache.httpcomponents httpcore - ${http-component-version} + ${httpcore.version} org.kie kie-ci - ${drools-version} + ${drools.version} org.drools drools-decisiontables - ${drools-version} + ${drools.version} org.drools drools-core - ${drools-version} + ${drools.version} org.drools drools-compiler - ${drools-version} + ${drools.version} org.apache.poi poi - ${apache-poi-version} + ${poi.version} org.apache.poi poi-ooxml - ${apache-poi-version} + ${poi.version} org.optaplanner optaplanner-core - ${opta-planner-version} + ${optaplanner-core.version} - 4.4.16 - 8.32.0.Final - 5.2.3 - 8.32.0.Final + 4.4.16 + 8.32.0.Final + 5.2.3 + 8.32.0.Final diff --git a/geotools/pom.xml b/geotools/pom.xml index 61682ae0f5..026a902fa9 100644 --- a/geotools/pom.xml +++ b/geotools/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 geotools - geotools jar + geotools com.baeldung diff --git a/google-auto-project/pom.xml b/google-auto-project/pom.xml index 175e0c20c6..f91c0d56f4 100644 --- a/google-auto-project/pom.xml +++ b/google-auto-project/pom.xml @@ -5,8 +5,8 @@ 4.0.0 google-auto-project 1.0 - google-auto-project pom + google-auto-project com.baeldung diff --git a/google-cloud/pom.xml b/google-cloud/pom.xml index 8bb535f12a..b4cc3ba72f 100644 --- a/google-cloud/pom.xml +++ b/google-cloud/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud - google-cloud jar + google-cloud Google Cloud Tutorials diff --git a/graphql-modules/pom.xml b/graphql-modules/pom.xml index 4b43cbffde..2525f75eff 100644 --- a/graphql-modules/pom.xml +++ b/graphql-modules/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.graphql graphql-modules - graphql-modules pom + graphql-modules com.baeldung diff --git a/grpc/pom.xml b/grpc/pom.xml index 758dc87c8f..31601a377e 100644 --- a/grpc/pom.xml +++ b/grpc/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 grpc - grpc jar + grpc com.baeldung diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml index be5a48c0cf..6829a74e81 100644 --- a/guava-modules/pom.xml +++ b/guava-modules/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 guava-modules - guava-modules 0.0.1-SNAPSHOT pom + guava-modules com.baeldung diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml index e0488bf0b1..aaf00b2588 100644 --- a/httpclient-simple/pom.xml +++ b/httpclient-simple/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 httpclient-simple - httpclient-simple war + httpclient-simple com.baeldung @@ -117,12 +117,7 @@ ${jstl.version} runtime - - - com.google.guava - guava - ${guava.version} - + diff --git a/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java b/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java new file mode 100644 index 0000000000..5f79a1a90b --- /dev/null +++ b/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java @@ -0,0 +1,24 @@ +package com.baeldung.image; + +import javax.imageio.ImageIO; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.File; + +public class Application { + + public static void main(String[] args) throws Exception { + BufferedImage srcImg = ImageIO.read(new File("src/main/resources/images/sampleImage.jpg")); + float scaleW = 2.0f, scaleH = 2.0f; + int w = srcImg.getWidth() * (int) scaleW; + int h = srcImg.getHeight() * (int) scaleH; + BufferedImage dstImg = new BufferedImage(w, h, srcImg.getType()); + AffineTransform scalingTransform = new AffineTransform(); + scalingTransform.scale(scaleW, scaleH); + AffineTransformOp scaleOp = new AffineTransformOp(scalingTransform, AffineTransformOp.TYPE_BILINEAR); + dstImg = scaleOp.filter(srcImg, dstImg); + ImageIO.write(dstImg, "jpg", new File("src/main/resources/images/resized.jpg")); + } + +} diff --git a/jackson-modules/jackson-annotations/pom.xml b/jackson-modules/jackson-annotations/pom.xml index 59d7d3d197..158b5b189a 100644 --- a/jackson-modules/jackson-annotations/pom.xml +++ b/jackson-modules/jackson-annotations/pom.xml @@ -59,7 +59,7 @@ 2.1.214 - 5.3.2 + 5.4.0 2.5.0 diff --git a/jackson-modules/jackson-conversions-2/pom.xml b/jackson-modules/jackson-conversions-2/pom.xml index 457045b460..d87d4334f3 100644 --- a/jackson-modules/jackson-conversions-2/pom.xml +++ b/jackson-modules/jackson-conversions-2/pom.xml @@ -56,7 +56,7 @@ 5.13.2 - 20220320 + 20240303 \ No newline at end of file diff --git a/jackson-modules/jackson-conversions/pom.xml b/jackson-modules/jackson-conversions/pom.xml index e0990ed34f..6d6af97785 100644 --- a/jackson-modules/jackson-conversions/pom.xml +++ b/jackson-modules/jackson-conversions/pom.xml @@ -28,6 +28,11 @@ jackson-databind ${jackson.version} + + com.google.guava + guava + ${guava.version} + diff --git a/jackson-modules/jackson-core/pom.xml b/jackson-modules/jackson-core/pom.xml index 4eccd4d8f8..9fd0cc4ac4 100644 --- a/jackson-modules/jackson-core/pom.xml +++ b/jackson-modules/jackson-core/pom.xml @@ -61,7 +61,7 @@ - 3.1.1 + 5.4.0 \ No newline at end of file diff --git a/jackson-modules/jackson-custom-conversions/pom.xml b/jackson-modules/jackson-custom-conversions/pom.xml index 31e460511a..c3ae4ae675 100644 --- a/jackson-modules/jackson-custom-conversions/pom.xml +++ b/jackson-modules/jackson-custom-conversions/pom.xml @@ -28,6 +28,11 @@ jackson-core ${jackson.version} + + com.google.guava + guava + ${guava.version} + diff --git a/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java b/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java index 127d466436..e1517ed09b 100644 --- a/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java +++ b/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java @@ -1,16 +1,5 @@ package com.baeldung.exceptions; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.List; - -import org.junit.Test; - import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonFactory; @@ -22,6 +11,13 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.*; public class JacksonExceptionsUnitTest { @@ -201,6 +197,16 @@ public class JacksonExceptionsUnitTest { .readValue(json); } + // JsonParseException: Unexpected character ('n' (code 110)) + @Test(expected = JsonParseException.class) + public void givenInvalidJsonString_whenDeserializing_thenException() throws JsonProcessingException, IOException { + final String json = "{\"id\":1, name:\"John\"}"; // Missing double quotes around 'name' + final ObjectMapper mapper = new ObjectMapper(); + mapper.reader() + .forType(User.class) + .readValue(json); + } + @Test public void givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect() throws JsonProcessingException, IOException { final String json = "{'id':1,'name':'John'}"; diff --git a/jackson-modules/jackson-jr/pom.xml b/jackson-modules/jackson-jr/pom.xml index 868c3ee17f..fdd7d85c70 100644 --- a/jackson-modules/jackson-jr/pom.xml +++ b/jackson-modules/jackson-jr/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 jackson-jr - jackson-jr pom + jackson-jr com.baeldung diff --git a/jackson-modules/pom.xml b/jackson-modules/pom.xml index e80340a4b9..4b249f12d2 100644 --- a/jackson-modules/pom.xml +++ b/jackson-modules/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 jackson-modules - jackson-modules 0.0.1-SNAPSHOT pom + jackson-modules com.baeldung @@ -31,11 +31,6 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml ${jackson.version} - - - com.google.guava - guava - ${guava.version} commons-io diff --git a/java-blockchain/pom.xml b/java-blockchain/pom.xml index 422867176f..06838b8080 100644 --- a/java-blockchain/pom.xml +++ b/java-blockchain/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.blockchain java-blockchain - java-blockchain jar + java-blockchain com.baeldung diff --git a/java-jdi/pom.xml b/java-jdi/pom.xml index 22d7743998..935d2a23e4 100644 --- a/java-jdi/pom.xml +++ b/java-jdi/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 java-jdi - java-jdi jar + java-jdi com.baeldung diff --git a/java-numbers-2/src/main/java/com/baeldung/rbg/Rgb.java b/java-numbers-2/src/main/java/com/baeldung/rbg/Rgb.java new file mode 100644 index 0000000000..536dbdd2eb --- /dev/null +++ b/java-numbers-2/src/main/java/com/baeldung/rbg/Rgb.java @@ -0,0 +1,46 @@ +package com.baeldung.rbg; + +import java.util.Objects; + +public class Rgb { + private int alpha; + private int red; + private int green; + private int blue; + + public Rgb(int alpha, int red, int green, int blue) { + this.alpha = alpha; + this.red = red; + this.green = green; + this.blue = blue; + } + + public int getAlpha() { + return alpha; + } + + public int getRed() { + return red; + } + + public int getGreen() { + return green; + } + + public int getBlue() { + return blue; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Rgb rgb = (Rgb) o; + return alpha == rgb.alpha && red == rgb.red && green == rgb.green && blue == rgb.blue; + } + + @Override + public int hashCode() { + return Objects.hash(alpha, red, green, blue); + } +} diff --git a/java-numbers-2/src/main/java/com/baeldung/rbg/RgbConversions.java b/java-numbers-2/src/main/java/com/baeldung/rbg/RgbConversions.java new file mode 100644 index 0000000000..fbf7615378 --- /dev/null +++ b/java-numbers-2/src/main/java/com/baeldung/rbg/RgbConversions.java @@ -0,0 +1,31 @@ +package com.baeldung.rbg; + +public class RgbConversions { + + public static int rgbToInt(int alpha, int red, int green, int blue) { + alpha = clamp(alpha, 0, 255); + red = clamp(red, 0, 255); + green = clamp(green, 0, 255); + blue = clamp(blue, 0, 255); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + public static int rgbToInt(Rgb rgb) { + return rgbToInt(rgb.getAlpha(), rgb.getRed(), rgb.getGreen(), rgb.getBlue()); + } + + public static Rgb intToRgb(int argb) { + int alpha = (argb >> 24) & 0xFF; + int red = (argb >> 16) & 0xFF; + int green = (argb >> 8) & 0xFF; + int blue = argb & 0xFF; + + return new Rgb(alpha, red, green, blue); + } + + private static int clamp(int value, int min, int max) { + return Math.max(min, Math.min(max, value)); + } +} + diff --git a/java-numbers-2/src/test/java/com/baeldung/rgb/RgbConversionUnitTest.java b/java-numbers-2/src/test/java/com/baeldung/rgb/RgbConversionUnitTest.java new file mode 100644 index 0000000000..6a52ab1d22 --- /dev/null +++ b/java-numbers-2/src/test/java/com/baeldung/rgb/RgbConversionUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.rgb; + +import com.baeldung.rbg.Rgb; +import com.baeldung.rbg.RgbConversions; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; + +public class RgbConversionUnitTest { + + @Test + public void whenBasicPackingAndUnpackingRgb_thenReturnInitialComponentsValues() { + int alpha = 255; + int red = 255; + int green = 0; + int blue = 0; + + int rgb = (alpha << 24) | (red << 16) | (green << 8) | blue; + + assertEquals(rgb, 0xFFFF0000); + + int alphaReconstructed = (rgb >> 24) & 0xFF; + int redReconstructed = (rgb >> 16) & 0xFF; + int greenReconstructed = (rgb >> 8) & 0xFF; + int blueReconstructed = rgb & 0xFF; + + assertEquals(alphaReconstructed, alpha); + assertEquals(redReconstructed, red); + assertEquals(greenReconstructed, green); + assertEquals(blueReconstructed, blue); + } + + @Test + public void whenRgbaToIntWithoutClamping_ReturnIntegerRepresentations() { + // Fully opaque red + assertEquals(0xFFFF0000, RgbConversions.rgbToInt(255, 255, 0, 0)); + // Fully transparent blue + assertEquals(0x000000FF, RgbConversions.rgbToInt(0, 0, 0, 255)); + // 50% transparent green + assertEquals(0x8000FF00, RgbConversions.rgbToInt(128, 0, 255, 0)); + } + + @Test + public void whenRgbaToIntWithClamping_ReturnIntegerRepresentations() { + // Clamping for values below 0 + assertEquals(0x00000000, RgbConversions.rgbToInt(-1, -1, -1, -1)); + // Clamping for values above 255 + assertEquals(0xFFFFFFFF, RgbConversions.rgbToInt(256, 256, 256, 256)); + } + + @Test + public void whenRgbaToIntBoundary_ReturnIntegerRepresentations() { + // Boundary values for each color component including alpha + assertEquals(0xFF000000, RgbConversions.rgbToInt(255, 0, 0, 0)); // Opaque black + assertEquals(0x00FFFFFF, RgbConversions.rgbToInt(0, 255, 255, 255)); // Transparent white + } + + @Test + public void whenRgbaToIntAndIntToRgb_ReturnTheSameValues() { + Rgb rgb = new Rgb(0, 125, 125, 100); + assertEquals(rgb, RgbConversions.intToRgb(RgbConversions.rgbToInt(rgb))); + } + + @Test + public void whenBrightnessAdjustment_ReturnChangedRgbIntegerValue() { + float scale = 0.8f; // darken by 20% + + // initial values + int alpha = 0; + int red = 100; + int green = 255; + int blue = 100; + + + int adjustedRed = (int)(red * scale); + int adjustedGreen = (int)(green * scale); + int adjustedBlue = (int)(blue * scale); + + int newArgb = (alpha << 24) | (adjustedRed << 16) | (adjustedGreen << 8) | adjustedBlue; + + assertEquals(newArgb, 0x50CC50); + } + + @Test + public void whenGrayscaleConversion_ReturnChangedRgbIntegerValue() { + float scale = 0.8f; // darken by 20% + + // initial values + int alpha = 0; + int red = 100; + int green = 255; + int blue = 100; + + int average = (int)(red * 0.299 + green * 0.587 + blue * 0.114); + int grayscaleArgb = (alpha << 24) | (average << 16) | (average << 8) | average; + + assertEquals(grayscaleArgb, 0xBEBEBE); + } + + @Test + public void whenInversion_ReturnChangedRgbIntegerValue() { + float scale = 0.8f; // darken by 20% + + // initial values + int alpha = 0; + int red = 100; + int green = 255; + int blue = 100; + + red = 255 - red; + green = 255 - green; + blue = 255 - blue; + + int invertedArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; + + assertEquals(invertedArgb, 0x9B009B); + } +} diff --git a/java-panama/pom.xml b/java-panama/pom.xml index 61c8f2c5be..75835ac693 100644 --- a/java-panama/pom.xml +++ b/java-panama/pom.xml @@ -5,8 +5,8 @@ com.baeldung.java.panama java-panama 1.0 - java-panama jar + java-panama diff --git a/javax-sound/pom.xml b/javax-sound/pom.xml index 6652022a40..bea1d7f93b 100644 --- a/javax-sound/pom.xml +++ b/javax-sound/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.javax-sound javax-sound - javax-sound jar + javax-sound com.baeldung diff --git a/jenkins-modules/pom.xml b/jenkins-modules/pom.xml index 5cbc47d1f4..7543f82145 100644 --- a/jenkins-modules/pom.xml +++ b/jenkins-modules/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 jenkins-modules - jenkins-modules pom + jenkins-modules parent-modules diff --git a/jetbrains/pom.xml b/jetbrains/pom.xml index 78d8b36b77..c1c7b8cdd8 100644 --- a/jetbrains/pom.xml +++ b/jetbrains/pom.xml @@ -5,8 +5,8 @@ 4.0.0 jetbrains 1.0-SNAPSHOT - jetbrains jar + jetbrains com.baeldung diff --git a/jgit/pom.xml b/jgit/pom.xml index 4e88808097..e91d3ae07b 100644 --- a/jgit/pom.xml +++ b/jgit/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 jgit - jgit jar + jgit com.baeldung diff --git a/jhipster-6/bookstore-monolith/pom.xml b/jhipster-6/bookstore-monolith/pom.xml index 110eec514b..a4f334fc1c 100644 --- a/jhipster-6/bookstore-monolith/pom.xml +++ b/jhipster-6/bookstore-monolith/pom.xml @@ -1150,7 +1150,7 @@ 3.23.1-GA - 3.6.3 + 4.9.1 3.6 5.1.5.RELEASE 2.0.1.Final @@ -1168,7 +1168,7 @@ 3.2.2 0.9.11 1.7.6 - 0.8.2 + 0.8.11 1.0.0 3.4.2 3.5.0.1254 diff --git a/jhipster-6/pom.xml b/jhipster-6/pom.xml index f2406d1bdb..b51aca02e3 100644 --- a/jhipster-6/pom.xml +++ b/jhipster-6/pom.xml @@ -5,8 +5,8 @@ com.baeldung.jhipster jhipster-6 1.0.0-SNAPSHOT - jhipster-6 pom + jhipster-6 parent-boot-2 diff --git a/jhipster-modules/jhipster-microservice/car-app/pom.xml b/jhipster-modules/jhipster-microservice/car-app/pom.xml index 069a1f6848..2fee5148a0 100644 --- a/jhipster-modules/jhipster-microservice/car-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/car-app/pom.xml @@ -24,7 +24,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 1.8 3.21.0-GA 1.0.0 diff --git a/jhipster-modules/jhipster-microservice/dealer-app/pom.xml b/jhipster-modules/jhipster-microservice/dealer-app/pom.xml index 43f9b046c7..509651e209 100644 --- a/jhipster-modules/jhipster-microservice/dealer-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/dealer-app/pom.xml @@ -24,7 +24,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/jhipster-modules/jhipster-microservice/gateway-app/pom.xml b/jhipster-modules/jhipster-microservice/gateway-app/pom.xml index 90d703b8c7..0e80a02e2e 100644 --- a/jhipster-modules/jhipster-microservice/gateway-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/gateway-app/pom.xml @@ -27,7 +27,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/jhipster-modules/jhipster-monolithic/pom.xml b/jhipster-modules/jhipster-monolithic/pom.xml index f1ee479756..6b06ba2e8b 100644 --- a/jhipster-modules/jhipster-monolithic/pom.xml +++ b/jhipster-modules/jhipster-monolithic/pom.xml @@ -893,7 +893,7 @@ 2.2.3 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/jhipster-modules/jhipster-uaa/pom.xml b/jhipster-modules/jhipster-uaa/pom.xml index 7c60f95e28..9085a07f0f 100644 --- a/jhipster-modules/jhipster-uaa/pom.xml +++ b/jhipster-modules/jhipster-uaa/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 jhipster-uaa - jhipster-uaa pom + jhipster-uaa jhipster-modules diff --git a/jhipster-modules/pom.xml b/jhipster-modules/pom.xml index 1e11d97f40..810f2b0c59 100644 --- a/jhipster-modules/pom.xml +++ b/jhipster-modules/pom.xml @@ -6,8 +6,8 @@ com.baeldung.jhipster jhipster-modules 1.0.0-SNAPSHOT - jhipster-modules pom + jhipster-modules ]](../lombok-2) \ No newline at end of file +- More articles: [[next -->]](../lombok-2) diff --git a/lombok-modules/pom.xml b/lombok-modules/pom.xml index 620f0bf74c..fd5af67a22 100644 --- a/lombok-modules/pom.xml +++ b/lombok-modules/pom.xml @@ -5,8 +5,8 @@ 4.0.0 lombok-modules 1.0.0-SNAPSHOT - lombok-modules pom + lombok-modules com.baeldung diff --git a/mapstruct/pom.xml b/mapstruct/pom.xml index 5332bcaeb3..277e4401d7 100644 --- a/mapstruct/pom.xml +++ b/mapstruct/pom.xml @@ -5,8 +5,8 @@ 4.0.0 mapstruct 1.0 - mapstruct jar + mapstruct com.baeldung diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java new file mode 100644 index 0000000000..f7bc88d95f --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java @@ -0,0 +1,208 @@ +package com.baeldung.mapstruct.enums.mapper; + +import com.baeldung.mapstruct.enums.model.*; +import org.mapstruct.*; +import org.mapstruct.factory.Mappers; + +/** + * The Traffic signal mapper. + */ +@Mapper +public interface TrafficSignalMapper { + + /** + * The constant INSTANCE. + */ + TrafficSignalMapper INSTANCE = Mappers.getMapper(TrafficSignalMapper.class); + + /** + * Convert traffic signal to integer. + * + * @param source the source + * @return the integer + */ + default Integer convertTrafficSignalToInteger(TrafficSignal source) { + Integer result = null; + switch (source) { + case Off: + result = 0; + break; + case Stop: + result = 1; + break; + case Go: + result = 2; + break; + } + return result; + } + + /** + * Maps road sign to traffic signal. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Move") + @ValueMapping(target = "Stop", source = "Halt") + TrafficSignal toTrafficSignal(RoadSign source); + + /** + * Maps string to traffic signal. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Move") + @ValueMapping(target = "Stop", source = "Halt") + TrafficSignal stringToTrafficSignal(String source); + + + /** + * Maps a traffic signal to string. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Go") + @ValueMapping(target = "Stop", source = "Stop") + String trafficSignalToString(TrafficSignal source); + + /** + * Maps a traffic signal to number. + * + * @param source the source + * @return the traffic signal number + */ + @Mapping(target = "number", source = ".") + TrafficSignalNumber trafficSignalToTrafficSignalNumber(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = "Stop") + SimpleTrafficSignal toSimpleTrafficSignal(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = MappingConstants.ANY_REMAINING) + SimpleTrafficSignal toSimpleTrafficSignalWithRemaining(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithUnmapped(TrafficSignal source); + + /** + * Maps traffic signal with null handling. + * + * @param source the source + * @return the work day + */ + @ValueMapping(target = "Off", source = MappingConstants.NULL) + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = MappingConstants.NULL, source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithNullHandling(TrafficSignal source); + + /** + * Maps simple traffic signal to traffic signal with exception handling. + * + * @param source the source + * @return the work day + * @throws IllegalArgumentException if {@code source} is {@code Sat} or {@code Sun}. + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.NULL) + @ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithExceptionHandling(TrafficSignal source); + + /** + * Apply suffix. + * + * @param source the source + * @return traffic signal suffixed + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION, configuration = "_Value") + TrafficSignalSuffixed applySuffix(TrafficSignal source); + + /** + * Apply prefix. + * + * @param source the source + * @return the traffic signal prefixed + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "Value_") + TrafficSignalPrefixed applyPrefix(TrafficSignal source); + + /** + * Strip suffix. + * + * @param source the source + * @return the traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION, configuration = "_Value") + TrafficSignal stripSuffix(TrafficSignalSuffixed source); + + /** + * Strip prefix. + * + * @param source the source + * @return the traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION, configuration = "Value_") + TrafficSignal stripPrefix(TrafficSignalPrefixed source); + + /** + * Apply lowercase to traffic signal. + * + * @param source the source + * @return the traffic signal lowercase + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "lower") + TrafficSignalLowercase applyLowercase(TrafficSignal source); + + /** + * Apply uppercase to traffic signal. + * + * @param source the source + * @return the traffic signal uppercase + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "upper") + TrafficSignalUppercase applyUppercase(TrafficSignal source); + + /** + * Underscore to string in capital case. + * + * @param source the source + * @return the string + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital") + String underscoreToCapital(TrafficSignalUnderscore source); + + /** + * Lowercase to capital traffic signal. + * + * @param source the source + * @return traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital") + TrafficSignal lowercaseToCapital(TrafficSignalLowercase source); +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java new file mode 100644 index 0000000000..1b846f98af --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum road signal. + */ +public enum RoadSign { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + Halt, + /** + * Go signal. + */ + Move +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java new file mode 100644 index 0000000000..fe58b42112 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java @@ -0,0 +1,15 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum two-state Traffic Signal. + */ +public enum SimpleTrafficSignal { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + On +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java new file mode 100644 index 0000000000..c3691435b5 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal. + */ +public enum TrafficSignal { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + Stop, + /** + * Go signal. + */ + Go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java new file mode 100644 index 0000000000..f603d2f2e3 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with lowercase. + */ +public enum TrafficSignalLowercase { + /** + * Off signal. + */ + off, + /** + * Stop signal. + */ + stop, + /** + * Go signal. + */ + go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java new file mode 100644 index 0000000000..8695babb39 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java @@ -0,0 +1,26 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The traffic signal number. + */ +public class TrafficSignalNumber { + private Integer number; + + /** + * Gets number. + * + * @return the number + */ + public Integer getNumber() { + return number; + } + + /** + * Sets number. + * + * @param number the number + */ + public void setNumber(Integer number) { + this.number = number; + } +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java new file mode 100644 index 0000000000..9af4fa8ae6 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with prefix. + */ +public enum TrafficSignalPrefixed { + /** + * Off signal. + */ + Value_Off, + /** + * Stop signal. + */ + Value_Stop, + /** + * Go signal. + */ + Value_Go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java new file mode 100644 index 0000000000..1de6c0ee14 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with suffix. + */ +public enum TrafficSignalSuffixed { + /** + * Off signal. + */ + Off_Value, + /** + * Stop signal. + */ + Stop_Value, + /** + * Go signal. + */ + Go_Value +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java new file mode 100644 index 0000000000..610df46587 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with uppercase. + */ +public enum TrafficSignalUnderscore { + /** + * Off signal. + */ + OFF_VALUE, + /** + * Stop signal. + */ + STOP_VALUE, + /** + * Go signal. + */ + GO_VALUE +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java new file mode 100644 index 0000000000..c9fd8f435d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with uppercase. + */ +public enum TrafficSignalUppercase { + /** + * Off signal. + */ + OFF, + /** + * Stop signal. + */ + STOP, + /** + * Go signal. + */ + GO +} diff --git a/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java new file mode 100644 index 0000000000..94d0f457aa --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java @@ -0,0 +1,249 @@ +package com.baeldung.mapstruct.enums; + +import com.baeldung.mapstruct.enums.mapper.TrafficSignalMapper; +import com.baeldung.mapstruct.enums.model.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +/** + * The traffic signal mapper test. + */ +class TrafficSignalMapperUnitTest { + + /** + * To traffic signal. + */ + @Test + void whenRoadSignIsMapped_thenGetTrafficSignal() { + RoadSign source = RoadSign.Move; + TrafficSignal target = TrafficSignalMapper.INSTANCE.toTrafficSignal(source); + assertEquals(TrafficSignal.Go, target); + } + + /** + * String to traffic signal. + */ + @Test + void whenStringIsMapped_thenGetTrafficSignal() { + String source = RoadSign.Move.name(); + TrafficSignal target = TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source); + assertEquals(TrafficSignal.Go, target); + } + + /** + * String to unmapped traffic signal. + */ + @Test + void whenStringIsUnmapped_thenGetException() { + String source = "Proceed"; + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source); + }); + assertEquals("Unexpected enum constant: " + source, exception.getMessage()); + } + + /** + * Traffic signal to string. + */ + @Test + void whenTrafficSignalIsMapped_thenGetString() { + TrafficSignal source = TrafficSignal.Go; + String targetTrafficSignalStr = TrafficSignalMapper.INSTANCE.trafficSignalToString(source); + assertEquals("Go", targetTrafficSignalStr); + } + + /** + * Traffic signal to int. + * + * @param source the traffic signal + * @param expected the expected traffic signal number + */ + @ParameterizedTest + @CsvSource({"Off,0", "Stop,1"}) + void whenTrafficSignalIsMapped_thenGetInt(TrafficSignal source, int expected) { + Integer targetTrafficSignalInt = TrafficSignalMapper.INSTANCE.convertTrafficSignalToInteger(source); + TrafficSignalNumber targetTrafficSignalNumber = TrafficSignalMapper.INSTANCE.trafficSignalToTrafficSignalNumber(source); + assertEquals(expected, targetTrafficSignalInt.intValue()); + assertEquals(expected, targetTrafficSignalNumber.getNumber().intValue()); + } + + /** + * Traffic signal to simple traffic signal. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMapped_thenGetSimpleTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignal(source); + assertEquals(expected, target); + } + + /** + * Traffic signal to working day. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMappedWithRemaining_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithRemaining(source); + assertEquals(expected, targetTrafficSignal); + } + + /** + * Traffic signal to working day. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMappedWithUnmapped_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithUnmapped(source); + assertEquals(expected, target); + } + + /** + * Traffic signal to simple traffic signal with null handling. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({",Off", "Go,On", "Stop,"}) + void whenTrafficSignalIsMappedWithNull_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithNullHandling(source); + assertEquals(expected, targetTrafficSignal); + } + + /** + * Traffic signal to traffic signal with exception handling. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({",", "Go,On", "Stop,"}) + void whenTrafficSignalIsMappedWithException_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + if (source == TrafficSignal.Go) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source); + assertEquals(expected, targetTrafficSignal); + } else { + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source); + }); + assertEquals("Unexpected enum constant: " + source, exception.getMessage()); + } + } + + /** + * Apply suffix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,Off_Value", "Go,Go_Value"}) + void whenTrafficSignalIsMappedWithSuffix_thenGetTrafficSignalSuffixed(TrafficSignal source, TrafficSignalSuffixed expected) { + TrafficSignalSuffixed result = TrafficSignalMapper.INSTANCE.applySuffix(source); + assertEquals(expected, result); + } + + /** + * Apply prefix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,Value_Off", "Go,Value_Go"}) + void whenTrafficSignalIsMappedWithPrefix_thenGetTrafficSignalPrefixed(TrafficSignal source, TrafficSignalPrefixed expected) { + TrafficSignalPrefixed result = TrafficSignalMapper.INSTANCE.applyPrefix(source); + assertEquals(expected, result); + } + + /** + * Strip suffix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off_Value,Off", "Go_Value,Go"}) + void whenTrafficSignalSuffixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalSuffixed source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.stripSuffix(source); + assertEquals(expected, result); + } + + /** + * Strip prefix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Value_Off,Off", "Value_Stop,Stop"}) + void whenTrafficSignalPrefixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalPrefixed source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.stripPrefix(source); + assertEquals(expected, result); + } + + /** + * Apply lowercase. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,off", "Go,go"}) + void whenTrafficSignalMappedWithLower_thenGetTrafficSignalLowercase(TrafficSignal source, TrafficSignalLowercase expected) { + TrafficSignalLowercase result = TrafficSignalMapper.INSTANCE.applyLowercase(source); + assertEquals(expected, result); + } + + /** + * Apply uppercase. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,OFF", "Go,GO"}) + void whenTrafficSignalMappedWithUpper_thenGetTrafficSignalUppercase(TrafficSignal source, TrafficSignalUppercase expected) { + TrafficSignalUppercase result = TrafficSignalMapper.INSTANCE.applyUppercase(source); + assertEquals(expected, result); + } + + /** + * Underscore to capital. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"OFF_VALUE,Off_Value", "GO_VALUE,Go_Value"}) + void whenTrafficSignalUnderscoreMappedWithCapital_thenGetStringCapital(TrafficSignalUnderscore source, String expected) { + String result = TrafficSignalMapper.INSTANCE.underscoreToCapital(source); + assertEquals(expected, result); + } + + /** + * Lowercase to capital. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"off,Off", "go,Go"}) + void whenTrafficSignalLowercaseMappedWithCapital_thenGetTrafficSignal(TrafficSignalLowercase source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.lowercaseToCapital(source); + assertEquals(expected, result); + } +} \ No newline at end of file diff --git a/maven-modules/animal-sniffer-mvn-plugin/pom.xml b/maven-modules/animal-sniffer-mvn-plugin/pom.xml index 0b508651af..04dbd722bb 100644 --- a/maven-modules/animal-sniffer-mvn-plugin/pom.xml +++ b/maven-modules/animal-sniffer-mvn-plugin/pom.xml @@ -5,8 +5,8 @@ 4.0.0 animal-sniffer-mvn-plugin 1.0-SNAPSHOT - animal-sniffer-mvn-plugin jar + animal-sniffer-mvn-plugin http://maven.apache.org diff --git a/maven-modules/dependency-exclusion/core-java-exclusions/pom.xml b/maven-modules/dependency-exclusion/core-java-exclusions/pom.xml index 9fd09f83e2..98fb78ddf3 100644 --- a/maven-modules/dependency-exclusion/core-java-exclusions/pom.xml +++ b/maven-modules/dependency-exclusion/core-java-exclusions/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-exclusions - core-java-exclusions jar + core-java-exclusions com.baeldung.dependency-exclusion @@ -19,7 +19,6 @@ junit test - diff --git a/maven-modules/dependency-exclusion/pom.xml b/maven-modules/dependency-exclusion/pom.xml index 93f7f3530e..2564058482 100644 --- a/maven-modules/dependency-exclusion/pom.xml +++ b/maven-modules/dependency-exclusion/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.dependency-exclusion dependency-exclusion - dependency-exclusion pom + dependency-exclusion com.baeldung @@ -35,10 +35,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.7.0 - 1.8 - 1.8 -parameters diff --git a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-aggregate-report/pom.xml b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-aggregate-report/pom.xml index 627a9f3206..052b07e8ea 100644 --- a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-aggregate-report/pom.xml +++ b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-aggregate-report/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.jacoco-coverage-aggregation jacoco-coverage-aggregate-report - jacoco-coverage-aggregate-report pom + jacoco-coverage-aggregate-report com.baeldung @@ -17,12 +17,12 @@ com.baeldung.jacoco-coverage-aggregation - services + jacoco-coverage-services-example ${project.parent.version} com.baeldung.jacoco-coverage-aggregation - controllers + jacoco-coverage-controllers-example ${project.parent.version} diff --git a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-controllers-example/pom.xml b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-controllers-example/pom.xml index 886e931224..90c3980e63 100644 --- a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-controllers-example/pom.xml +++ b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-controllers-example/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.jacoco-coverage-aggregation jacoco-coverage-controllers-example - jacoco-coverage-controllers-example jar + jacoco-coverage-controllers-example com.baeldung @@ -17,7 +17,7 @@ com.baeldung.jacoco-coverage-aggregation - services + jacoco-coverage-services-example ${project.parent.version} diff --git a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-services-example/pom.xml b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-services-example/pom.xml index 223689f8ff..048511c1ad 100644 --- a/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-services-example/pom.xml +++ b/maven-modules/jacoco-coverage-aggregation/jacoco-coverage-services-example/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.jacoco-coverage-aggregation jacoco-coverage-services-example - jacoco-coverage-services-example jar + jacoco-coverage-services-example com.baeldung @@ -33,7 +33,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + ${maven-surefire-plugin.version} **/*Test.java @@ -46,6 +46,7 @@ 5.9.2 6.0.11 + 3.1.2 \ No newline at end of file diff --git a/maven-modules/jacoco-coverage-aggregation/pom.xml b/maven-modules/jacoco-coverage-aggregation/pom.xml index 6d1aab3c3d..274a19c723 100644 --- a/maven-modules/jacoco-coverage-aggregation/pom.xml +++ b/maven-modules/jacoco-coverage-aggregation/pom.xml @@ -3,17 +3,15 @@ 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 jacoco-coverage-aggregation 1.0 - jacoco-coverage-aggregation pom + jacoco-coverage-aggregation com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ + maven-modules + 0.0.1-SNAPSHOT @@ -40,7 +38,7 @@ - 0.8.8 + 0.8.11 \ No newline at end of file diff --git a/maven-modules/maven-archetype/pom.xml b/maven-modules/maven-archetype/pom.xml index 04247f622c..5fd0b0cbb9 100644 --- a/maven-modules/maven-archetype/pom.xml +++ b/maven-modules/maven-archetype/pom.xml @@ -6,8 +6,8 @@ com.baeldung.archetypes maven-archetype 1.0-SNAPSHOT - maven-archetype maven-archetype + maven-archetype Archetype used to generate rest application based on jaxrs 2.1 @@ -21,8 +21,6 @@ - 1.8 - 1.8 3.0.1 diff --git a/maven-modules/maven-build-lifecycle/pom.xml b/maven-modules/maven-build-lifecycle/pom.xml index 5cfb854200..f9025a9c46 100644 --- a/maven-modules/maven-build-lifecycle/pom.xml +++ b/maven-modules/maven-build-lifecycle/pom.xml @@ -1,24 +1,16 @@ + 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 + maven-build-lifecycle + com.baeldung maven-modules 0.0.1-SNAPSHOT - maven-build-lifecycle - - - 11 - 11 - 3.1.2 - 3.1.2 - 5.3.1 - UTF-8 - @@ -52,4 +44,10 @@ + + 3.1.2 + 3.1.2 + 5.3.1 + + \ No newline at end of file diff --git a/maven-modules/maven-build-optimization/pom.xml b/maven-modules/maven-build-optimization/pom.xml index 86d3b2d34f..30e96fb2be 100644 --- a/maven-modules/maven-build-optimization/pom.xml +++ b/maven-modules/maven-build-optimization/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-build-optimization 0.0.1-SNAPSHOT - maven-build-optimization pom + maven-build-optimization com.baeldung diff --git a/maven-modules/maven-builder-plugin/pom.xml b/maven-modules/maven-builder-plugin/pom.xml index 338aafe85d..75211fda1a 100644 --- a/maven-modules/maven-builder-plugin/pom.xml +++ b/maven-modules/maven-builder-plugin/pom.xml @@ -7,6 +7,12 @@ maven-builder-plugin 1.0-SNAPSHOT + + com.baeldung + maven-modules + 0.0.1-SNAPSHOT + + @@ -32,10 +38,7 @@ - 3.2.0 - 1.8 - 1.8 - UTF-8 + 3.4.0 \ No newline at end of file diff --git a/maven-modules/maven-classifier/maven-classifier-example-consumer/pom.xml b/maven-modules/maven-classifier/maven-classifier-example-consumer/pom.xml index b64fe94e46..cb0583d6a0 100644 --- a/maven-modules/maven-classifier/maven-classifier-example-consumer/pom.xml +++ b/maven-modules/maven-classifier/maven-classifier-example-consumer/pom.xml @@ -45,9 +45,4 @@ - - 8 - 8 - - \ No newline at end of file diff --git a/maven-modules/maven-classifier/pom.xml b/maven-modules/maven-classifier/pom.xml index bcbbcdd49e..a61cd8b0c5 100644 --- a/maven-modules/maven-classifier/pom.xml +++ b/maven-modules/maven-classifier/pom.xml @@ -18,9 +18,4 @@ maven-classifier-example-provider - - 8 - 8 - - \ No newline at end of file diff --git a/maven-modules/maven-copy-files/pom.xml b/maven-modules/maven-copy-files/pom.xml index 57d0ddf647..90b40171a7 100644 --- a/maven-modules/maven-copy-files/pom.xml +++ b/maven-modules/maven-copy-files/pom.xml @@ -3,11 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung maven-copy-files 1.0-SNAPSHOT - maven-copy-files pom + maven-copy-files http://www.example.com @@ -78,10 +77,4 @@ - - UTF-8 - 1.7 - 1.7 - - \ No newline at end of file diff --git a/maven-modules/maven-custom-plugin/counter-maven-plugin/pom.xml b/maven-modules/maven-custom-plugin/counter-maven-plugin/pom.xml index 9648464102..38e5119dd4 100644 --- a/maven-modules/maven-custom-plugin/counter-maven-plugin/pom.xml +++ b/maven-modules/maven-custom-plugin/counter-maven-plugin/pom.xml @@ -6,8 +6,8 @@ com.baeldung counter-maven-plugin 0.0.1-SNAPSHOT - counter-maven-plugin maven-plugin + counter-maven-plugin http://maven.apache.org @@ -56,6 +56,7 @@ org.apache.maven.plugins maven-plugin-plugin + ${maven-compiler-plugin.version} @@ -68,12 +69,13 @@ - 1.8 - 1.8 + 3.12.1 + 17 + 17 3.6.2 3.6.0 2.2.1 - 3.6.0 + 3.11.0 3.8.2 diff --git a/maven-modules/maven-custom-plugin/pom.xml b/maven-modules/maven-custom-plugin/pom.xml index 731abe472d..2931789830 100644 --- a/maven-modules/maven-custom-plugin/pom.xml +++ b/maven-modules/maven-custom-plugin/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-custom-plugin 0.0.1-SNAPSHOT - maven-custom-plugin pom + maven-custom-plugin com.baeldung diff --git a/maven-modules/maven-exec-plugin/pom.xml b/maven-modules/maven-exec-plugin/pom.xml index fc4d2d79f1..cddc693bf3 100644 --- a/maven-modules/maven-exec-plugin/pom.xml +++ b/maven-modules/maven-exec-plugin/pom.xml @@ -3,11 +3,16 @@ 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 maven-exec-plugin 0.0.1-SNAPSHOT maven-exec-plugin + + com.baeldung + maven-modules + 0.0.1-SNAPSHOT + + org.apache.maven.shared @@ -37,6 +42,17 @@ ${junit.jupiter.version} test + + org.junit.vintage + junit-vintage-engine + ${junit.jupiter.version} + + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + test + diff --git a/maven-modules/maven-generate-war/pom.xml b/maven-modules/maven-generate-war/pom.xml index 1d7c79aa81..ab2413385b 100644 --- a/maven-modules/maven-generate-war/pom.xml +++ b/maven-modules/maven-generate-war/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-generate-war 0.0.1-SNAPSHOT - maven-generate-war war + maven-generate-war Spring boot project to demonstrate war file generation @@ -59,10 +59,6 @@ org.apache.maven.plugins maven-compiler-plugin - - ${maven.compiler.source.version} - ${maven.compiler.target.version} - diff --git a/maven-modules/maven-integration-test/pom.xml b/maven-modules/maven-integration-test/pom.xml index 7c604b121b..261a885ce3 100644 --- a/maven-modules/maven-integration-test/pom.xml +++ b/maven-modules/maven-integration-test/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-integration-test 0.0.1-SNAPSHOT - maven-integration-test war + maven-integration-test com.baeldung @@ -273,7 +273,7 @@ 1.1 3.0.0 3.0.0 - 9.4.11.v20180605 + 10.0.20 2.27 diff --git a/maven-modules/maven-multi-source/pom.xml b/maven-modules/maven-multi-source/pom.xml index 96b390d75a..7de02c17de 100644 --- a/maven-modules/maven-multi-source/pom.xml +++ b/maven-modules/maven-multi-source/pom.xml @@ -20,8 +20,6 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - ${java.version} - ${java.version} -Xlint:unchecked diff --git a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/empty-phase/pom.xml b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/empty-phase/pom.xml index 28ea8b6359..7259ce4d20 100644 --- a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/empty-phase/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/empty-phase/pom.xml @@ -3,7 +3,6 @@ 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.maven-parent-pom-resolution empty-phase 1.0.0-SNAPSHOT pom diff --git a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/phase-none/pom.xml b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/phase-none/pom.xml index 8870f28fd2..3da1de339e 100644 --- a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/phase-none/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/phase-none/pom.xml @@ -3,7 +3,6 @@ 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.maven-parent-pom-resolution phase-none 1.0.0-SNAPSHOT pom diff --git a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/plugin-enabled/pom.xml b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/plugin-enabled/pom.xml index e3ff22aaf7..fd62bf84c7 100644 --- a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/plugin-enabled/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/plugin-enabled/pom.xml @@ -3,7 +3,6 @@ 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.maven-parent-pom-resolution plugin-enabled 1.0.0-SNAPSHOT pom diff --git a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/pom.xml b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/pom.xml index 4d16a94838..92e5da680a 100644 --- a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/pom.xml @@ -26,7 +26,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0 + ${maven-enforcer-plugin.version} enforce-file-exists @@ -49,7 +49,7 @@ - UTF-8 + 3.0.0 \ No newline at end of file diff --git a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/skip-parameter/pom.xml b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/skip-parameter/pom.xml index 31415bec24..57a608b043 100644 --- a/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/skip-parameter/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/disable-plugin-examples/skip-parameter/pom.xml @@ -3,7 +3,6 @@ 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.maven-parent-pom-resolution skip-parameter 1.0.0-SNAPSHOT pom diff --git a/maven-modules/maven-plugins/pom.xml b/maven-modules/maven-plugins/pom.xml index 4aa295c8a8..e3d67d65ff 100644 --- a/maven-modules/maven-plugins/pom.xml +++ b/maven-modules/maven-plugins/pom.xml @@ -43,8 +43,6 @@ maven-compiler-plugin ${maven.compiler.version} - ${java.version} - ${java.version} -Xlint:unchecked diff --git a/maven-modules/maven-polyglot/pom.xml b/maven-modules/maven-polyglot/pom.xml index 7ff375b9ba..3583563aba 100644 --- a/maven-modules/maven-polyglot/pom.xml +++ b/maven-modules/maven-polyglot/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-polyglot 0.0.1-SNAPSHOT - maven-polyglot pom + maven-polyglot com.baeldung diff --git a/maven-modules/maven-printing-plugins/pom.xml b/maven-modules/maven-printing-plugins/pom.xml index 683a99fef7..264185413a 100644 --- a/maven-modules/maven-printing-plugins/pom.xml +++ b/maven-modules/maven-printing-plugins/pom.xml @@ -17,7 +17,7 @@ maven-antrun-plugin - 3.0.0 + ${maven-antrun-plugin.version} antrun-plugin @@ -41,7 +41,7 @@ com.github.ekryd.echo-maven-plugin echo-maven-plugin - 1.3.2 + ${echo-maven-plugin.version} echo-maven-plugin-1 @@ -66,7 +66,7 @@ org.codehaus.gmaven groovy-maven-plugin - 2.1.1 + ${groovy-maven-plugin.version} validate @@ -87,4 +87,10 @@ + + 3.0.0 + 1.3.2 + 2.1.1 + + \ No newline at end of file diff --git a/maven-modules/maven-properties/pom.xml b/maven-modules/maven-properties/pom.xml index f28c353074..f3ed102f4d 100644 --- a/maven-modules/maven-properties/pom.xml +++ b/maven-modules/maven-properties/pom.xml @@ -61,7 +61,6 @@ - UTF-8 UTF-8 diff --git a/maven-modules/maven-reactor/patient-web/pom.xml b/maven-modules/maven-reactor/patient-web/pom.xml index 9d2ddd819d..eb1ec57382 100644 --- a/maven-modules/maven-reactor/patient-web/pom.xml +++ b/maven-modules/maven-reactor/patient-web/pom.xml @@ -6,11 +6,13 @@ patient-web 1.0-SNAPSHOT patient-web + com.baeldung maven-reactor 1.0-SNAPSHOT + com.baeldung diff --git a/maven-modules/multimodulemavenproject/maven-userdaomodule/pom.xml b/maven-modules/multimodulemavenproject/maven-userdaomodule/pom.xml index c7ceada17d..d5fe513e09 100644 --- a/maven-modules/multimodulemavenproject/maven-userdaomodule/pom.xml +++ b/maven-modules/multimodulemavenproject/maven-userdaomodule/pom.xml @@ -17,12 +17,12 @@ com.baeldung.entitymodule - entitymodule + maven-entitymodule ${entitymodule.version} com.baeldung.daomodule - daomodule + maven-daomodule ${daomodule.version} @@ -41,8 +41,6 @@
- 9 - 9 1.0 1.0 diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index 5e293fdb02..956ae917ac 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -27,7 +27,7 @@ maven-classifier maven-copy-files maven-custom-plugin - maven-exec-plugin + maven-generate-war maven-integration-test maven-multi-source @@ -84,4 +84,7 @@
+ + 3.1.0 + \ No newline at end of file diff --git a/maven-modules/version-overriding-plugins/pom.xml b/maven-modules/version-overriding-plugins/pom.xml index d38541d797..1f3106df3b 100644 --- a/maven-modules/version-overriding-plugins/pom.xml +++ b/maven-modules/version-overriding-plugins/pom.xml @@ -30,6 +30,7 @@ maven-resources-plugin + ${maven-resources-plugin.version} diff --git a/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml b/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml index 48b5782f72..e54768b5c3 100644 --- a/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml +++ b/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml @@ -16,6 +16,7 @@ maven-resources-plugin + ${maven-resources-plugin.version} diff --git a/maven-modules/versions-maven-plugin/pom.xml b/maven-modules/versions-maven-plugin/pom.xml index ec1e0ceaba..39a345a506 100644 --- a/maven-modules/versions-maven-plugin/pom.xml +++ b/maven-modules/versions-maven-plugin/pom.xml @@ -3,7 +3,6 @@ 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 versions-maven-plugin 0.0.1-SNAPSHOT versions-maven-plugin diff --git a/mesos-marathon/Dockerfile b/mesos-marathon/Dockerfile index ca79f2dc82..40705a3206 100644 --- a/mesos-marathon/Dockerfile +++ b/mesos-marathon/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:8-jre-alpine +FROM openjdk:17-jdk-alpine ADD target/mesos-marathon-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8082 ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/mesos-marathon/pom.xml b/mesos-marathon/pom.xml index 58ca14ca93..0d42ef6b00 100644 --- a/mesos-marathon/pom.xml +++ b/mesos-marathon/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 diff --git a/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java index dfe944a316..e4878cd92a 100644 --- a/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java +++ b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java @@ -4,7 +4,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.client.RestTemplate; diff --git a/messaging-modules/java-redpanda/README.md b/messaging-modules/java-redpanda/README.md new file mode 100644 index 0000000000..36ee68b5bb --- /dev/null +++ b/messaging-modules/java-redpanda/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Introduction to Redpanda](https://www.baeldung.com/redpanda) diff --git a/messaging-modules/java-redpanda/pom.xml b/messaging-modules/java-redpanda/pom.xml new file mode 100644 index 0000000000..a9a9e2f4ea --- /dev/null +++ b/messaging-modules/java-redpanda/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + java-redpanda + java-redpanda + + com.baeldung + messaging-modules + 0.0.1-SNAPSHOT + + + + + org.apache.kafka + kafka-clients + ${kafka.version} + + + + org.testcontainers + junit-jupiter + ${testcontainers-jupiter.version} + test + + + + org.testcontainers + testcontainers + test + + + + org.testcontainers + redpanda + ${redpanda.version} + + + + + + + + org.testcontainers + testcontainers-bom + 1.19.3 + pom + import + + + + + + 1.19.4 + 3.6.1 + 1.15.3 + UTF-8 + + + diff --git a/messaging-modules/java-redpanda/src/main/java/com/baeldung/redpanda/Application.java b/messaging-modules/java-redpanda/src/main/java/com/baeldung/redpanda/Application.java new file mode 100644 index 0000000000..15026a7b4c --- /dev/null +++ b/messaging-modules/java-redpanda/src/main/java/com/baeldung/redpanda/Application.java @@ -0,0 +1,7 @@ +package com.baeldung.redpanda; + + +public class Application { + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/messaging-modules/java-redpanda/src/test/java/com/baeldung/redpanda/RedpandaLiveTest.java b/messaging-modules/java-redpanda/src/test/java/com/baeldung/redpanda/RedpandaLiveTest.java new file mode 100644 index 0000000000..0dcbc4d2b2 --- /dev/null +++ b/messaging-modules/java-redpanda/src/test/java/com/baeldung/redpanda/RedpandaLiveTest.java @@ -0,0 +1,151 @@ +package com.baeldung.redpanda; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.ExecutionException; + +import org.apache.kafka.clients.admin.AdminClient; +import org.apache.kafka.clients.admin.AdminClientConfig; +import org.apache.kafka.clients.admin.KafkaAdminClient; +import org.apache.kafka.clients.admin.NewTopic; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.Network; +import org.testcontainers.redpanda.RedpandaContainer; + +public class RedpandaLiveTest { + private static final Logger LOGGER = LoggerFactory.getLogger(RedpandaLiveTest.class); + + private static RedpandaContainer redpandaContainer = null; + + private static final String TOPIC_NAME = "baeldung"; + + private static final Integer BROKER_PORT = 9092; + + @BeforeAll + static void setup() throws ExecutionException, InterruptedException { + installRedpanda(); + + createTopic(TOPIC_NAME); + + publishMessages(TOPIC_NAME); + } + + @AfterAll + static void cleanup() { + redpandaContainer.stop(); + } + + private static void publishMessages(String topic) throws ExecutionException, InterruptedException { + try (final KafkaProducer producer = createProducer()) { + for (int i = 0; i < 10; i++) { + publishMessage("test_msg_key_1_" + i, "How are you redpanda:" + i, topic, producer); + } + } + } + + private static void installRedpanda() { + final String DOCKER_IMAGE = "docker.redpanda.com/redpandadata/redpanda:v23.1.2"; + Network network = Network.newNetwork(); + redpandaContainer = new RedpandaContainer(DOCKER_IMAGE).withNetwork(network) + .withNetworkAliases("redpanda") + .withExposedPorts(BROKER_PORT); + redpandaContainer.start(); + } + + private static AdminClient createAdminClient() { + Properties adminProps = new Properties(); + adminProps.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, getBrokerUrl()); + return KafkaAdminClient.create(adminProps); + } + + private static void createTopic(String topicName) { + + try (AdminClient adminClient = createAdminClient()) { + NewTopic topic = new NewTopic(topicName, 1, (short) 1); + adminClient.createTopics(Collections.singleton(topic)); + } catch (Exception e) { + LOGGER.error("Error occurred during topic creation:", e); + } + } + + private static KafkaProducer createProducer() { + Properties producerProps = new Properties(); + producerProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, getBrokerUrl()); + producerProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + producerProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + + return new KafkaProducer(producerProps); + } + + private static KafkaConsumer createConsumer() { + Properties consumerProps = new Properties(); + consumerProps.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + consumerProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, getBrokerUrl()); + consumerProps.put(ConsumerConfig.GROUP_ID_CONFIG, "test-consumer-group"); + consumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + + return new KafkaConsumer(consumerProps); + } + + private static void publishMessage(String msgKey, String msg, String topic, KafkaProducer producer) + throws ExecutionException, InterruptedException { + ProducerRecord record = new ProducerRecord<>(topic, msgKey, msg); + producer.send(record).get(); + } + + private static String getBrokerUrl() { + return redpandaContainer.getHost() + ":" + redpandaContainer.getMappedPort(BROKER_PORT); + } + + @Test + void whenCreateTopic_thenSuccess() throws ExecutionException, InterruptedException { + String topic = "test-topic"; + createTopic(topic); + try(AdminClient adminClient = createAdminClient()) { + assertTrue(adminClient.listTopics() + .names() + .get() + .contains(topic)); + } + } + + @Test + void givenTopic_whenPublishMsg_thenSuccess() { + try (final KafkaProducer producer = createProducer()) { + assertDoesNotThrow(() -> publishMessage("test_msg_key_2", "Hello Redpanda!", "baeldung-topic", producer)); + } + } + + @Test + void givenTopic_whenConsumeMessage_thenSuccess() { + try (KafkaConsumer kafkaConsumer = createConsumer()) { + kafkaConsumer.subscribe(Collections.singletonList(TOPIC_NAME)); + + while(true) { + ConsumerRecords records = kafkaConsumer.poll(Duration.ofMillis(1000)); + if(records.count() == 0) { + continue; + } + assertTrue(records.count() >= 1); + break; + } + } + } +} diff --git a/messaging-modules/pom.xml b/messaging-modules/pom.xml index 3642eb4260..3c70c66c20 100644 --- a/messaging-modules/pom.xml +++ b/messaging-modules/pom.xml @@ -18,6 +18,7 @@ apache-camel apache-rocketmq jgroups + java-redpanda rabbitmq spring-amqp spring-apache-camel diff --git a/metrics/pom.xml b/metrics/pom.xml index a8f5e113e8..0e06a479c3 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -85,7 +85,7 @@ 4.2.17 0.13.2 - 1.11.0 + 1.12.3 3.1.0 1.2.0 1.7.7 diff --git a/microservices-modules/micronaut/pom.xml b/microservices-modules/micronaut/pom.xml index fa73a15ac4..641b23d5e6 100644 --- a/microservices-modules/micronaut/pom.xml +++ b/microservices-modules/micronaut/pom.xml @@ -101,6 +101,7 @@ io.micronaut.build micronaut-maven-plugin + ${micronaut-build.version} org.apache.maven.plugins @@ -154,6 +155,7 @@ jar 3.12.1 netty + 3.5.4 3.2.0 diff --git a/microservices-modules/saga-pattern/README.md b/microservices-modules/saga-pattern/README.md new file mode 100644 index 0000000000..95a090fe72 --- /dev/null +++ b/microservices-modules/saga-pattern/README.md @@ -0,0 +1,16 @@ +# Saga Pattern Using Orkes Conductor + +This is an example project showing how to build event driven applications using [Conductor](https://github.com/conductor-oss/conductor) + +# Pre-requisites +1. Docker +2. Running conductor server + +**Start the conductor server** + +```shell +docker run --init -p 8080:8080 -p 1234:5000 conductoross/conductor-standalone:3.15.0 +``` + +### Relevant Articles: +- [Saga Pattern in Microservices Architecture](https://www.baeldung.com/orkes-conductor-saga-pattern-spring-boot) diff --git a/microservices-modules/saga-pattern/build.gradle b/microservices-modules/saga-pattern/build.gradle new file mode 100644 index 0000000000..adf0a913db --- /dev/null +++ b/microservices-modules/saga-pattern/build.gradle @@ -0,0 +1,34 @@ +buildscript { + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:3.2.3" + } +} + +plugins { + id 'java' + id 'org.springframework.boot' version '3.2.3' + id 'io.freefair.lombok' version '8.6' +} + +apply plugin: 'io.spring.dependency-management' + +group = 'io.orkes.example' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' + + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'io.orkes.conductor:orkes-conductor-client:2.1.0' + + implementation 'org.xerial:sqlite-jdbc:3.32.3.3' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/microservices-modules/saga-pattern/settings.gradle b/microservices-modules/saga-pattern/settings.gradle new file mode 100644 index 0000000000..8a06313387 --- /dev/null +++ b/microservices-modules/saga-pattern/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'conductor-examples-food-delivery' + diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java new file mode 100644 index 0000000000..17262cdf0a --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java @@ -0,0 +1,28 @@ +package io.orkes.example.saga; + +import io.orkes.example.saga.dao.BaseDAO; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import lombok.AllArgsConstructor; + + +@AllArgsConstructor +@SpringBootApplication +@ComponentScan(basePackages = {"io.orkes"}) +public class SagaApplication { + + private static final BaseDAO db = new BaseDAO("jdbc:sqlite:food_delivery.db"); + + public static void main(String[] args) { + SpringApplication.run(SagaApplication.class, args); + initDB(); + } + + public static void initDB() { + db.createTables("orders"); + db.createTables("inventory"); + db.createTables("payments"); + db.createTables("shipments"); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java new file mode 100644 index 0000000000..febc05e74b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java @@ -0,0 +1,27 @@ +package io.orkes.example.saga.controller; + +import io.orkes.example.saga.pojos.FoodDeliveryRequest; +import io.orkes.example.saga.pojos.OrderRequest; +import io.orkes.example.saga.service.WorkflowService; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@Slf4j +@AllArgsConstructor +@RestController +public class OrderServiceController { + + private final WorkflowService workflowService; + + @PostMapping(value = "/triggerFoodDeliveryFlow", produces = "application/json") + public ResponseEntity> triggerFoodDeliveryFlow(@RequestBody FoodDeliveryRequest foodDeliveryRequest) { + return ResponseEntity.ok(workflowService.startFoodDeliveryWorkflow(foodDeliveryRequest)); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java new file mode 100644 index 0000000000..9f077929dc --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java @@ -0,0 +1,221 @@ +package io.orkes.example.saga.dao; + +import java.sql.*; + +public class BaseDAO { + + private String url; + + public BaseDAO(String url) { + this.url = url; + } + + protected Connection connect() { + Connection conn = null; + try { + conn = DriverManager.getConnection(this.url); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return conn; + } + + protected Boolean execute(String sql) { + try (Connection conn = DriverManager.getConnection(this.url); Statement stmt = conn.createStatement()) { + stmt.execute(sql); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return false; + } + return true; + } + + public void createTables(String service) { + switch (service) { + case "orders": + createOrdersTable(); + createOrderDetailsTable(); + createCustomerTable(); + break; + case "inventory": + createRestaurantsTable(); + break; + case "shipments": + createDriversTable(); + createShipmentTable(); + break; + case "payments": + createPaymentsTable(); + break; + default: + System.out.println("Service name not recognized"); + } + } + + private void createOrdersTable() { + if (!tableExists("orders")) { + + String sql = "CREATE TABLE orders (\n" + + " orderId text PRIMARY KEY,\n" + + " customerId integer NOT NULL,\n" + + " restaurantId integer NOT NULL,\n" + + " deliveryAddress text NOT NULL,\n" + + " createdAt TIMESTAMP NOT NULL,\n" + + " status text NOT NULL\n" + + ");"; + + execute(sql); + } + } + + private void createOrderDetailsTable() { + if (!tableExists("orders_details")) { + String sql = "CREATE TABLE orders_details (\n" + + " orderId text PRIMARY KEY,\n" + + " items text NOT NULL,\n" + + " notes text\n" + + ");"; + + execute(sql); + } + } + + private void createCustomerTable() { + if (tableExists("customers")) { + return; + } + + String sql = "CREATE TABLE customers (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " email text NOT NULL,\n" + + " name text NOT NULL,\n" + + " contact text\n" + + ");"; + + if(execute(sql)) { + seedCustomers(); + } + } + + private void createRestaurantsTable() { + if (!tableExists("restaurants")) { + String sql = "CREATE TABLE restaurants (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " name text NOT NULL,\n" + + " address text NOT NULL,\n" + + " contact text NOT NULL\n" + + ");"; + + if (execute(sql)) { + seedRestaurants(); + } + } + } + + + private void createPaymentsTable() { + if (tableExists("payments")) { + return; + } + + String sql = "CREATE TABLE payments (\n" + + " paymentId text PRIMARY KEY,\n" + + " orderId text NOT NULL,\n" + + " amount number NOT NULL,\n" + + " method text,\n" + + " status text,\n" + + " createdAt TIMESTAMP NOT NULL\n" + + ");"; + + execute(sql); + } + + private void createDriversTable() { + if (tableExists("drivers")) { + return; + } + + String sql = "CREATE TABLE drivers (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " name text NOT NULL,\n" + + " contact text\n" + + ");"; + + if(execute(sql)) { + seedDrivers(); + } + } + private void createShipmentTable() { + if (tableExists("shipments")) { + return; + } + + String sql = "CREATE TABLE shipments (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " orderId text NOT NULL,\n" + + " driverId number NOT NULL,\n" + + " address text NOT NULL,\n" + + " instructions text,\n" + + " status text NOT NULL,\n" + + " createdAt TIMESTAMP NOT NULL\n" + + ");"; + + execute(sql); + } + + private void seedCustomers() { + String[] queries = { + "INSERT INTO customers(email, name, contact) VALUES('John Smith','john.smith@example.com','+12126781345');", + "INSERT INTO customers(email, name, contact) VALUES('Mike Ross','mike.ross@example.com','+15466711147');", + "INSERT INTO customers(email, name, contact) VALUES('Martha Williams','martha.williams@example.com','+12790581941');" + }; + + for (String query : queries) { + execute(query); + } + } + + private void seedRestaurants() { + String[] add = { + "5331 Redford Court, Montgomery AL 36116", + "43 West 4th Street, New York NY 10024", + "1693 Alice Court, Annapolis MD 21401" + }; + String[] queries = { + "INSERT INTO restaurants(name, address, contact) VALUES('Mikes','+12121231345','" + add[0] + "');", + "INSERT INTO restaurants(name, address, contact) VALUES('Tamarind','+12412311147','" + add[1] + "');", + "INSERT INTO restaurants(name, address, contact) VALUES('Thai Place','+14790981941','" + add[2] + "');", + }; + + for (String query : queries) { + execute(query); + } + } + + private void seedDrivers() { + String[] queries = { + "INSERT INTO drivers(name,contact) VALUES('Wayne Stevens','+12520711467');", + "INSERT INTO drivers(name,contact) VALUES('Jim Willis','+16466281981');", + "INSERT INTO drivers(name,contact) VALUES('Steven Carroll','+12612590430');", + "INSERT INTO drivers(name,contact) VALUES('Tom Cruise','+18659581430');" + }; + + for (String query : queries) { + execute(query); + } + } + + boolean tableExists(String tableName) { + try { + Connection conn = DriverManager.getConnection(this.url); + DatabaseMetaData meta = conn.getMetaData(); + ResultSet resultSet = meta.getTables(null, null, tableName, new String[] {"TABLE"}); + boolean exists = resultSet.next(); + conn.close(); + return exists; + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return false; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java new file mode 100644 index 0000000000..e347b90994 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java @@ -0,0 +1,33 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Order; +import io.orkes.example.saga.pojos.Restaurant; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class InventoryDAO extends BaseDAO { + + public InventoryDAO(String url) { + super(url); + } + + public void readRestaurant(int restaurantId, Restaurant restaurant) { + String sql = "SELECT name, address, contact FROM restaurants WHERE id = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, restaurantId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + restaurant.setName(rs.getString("name")); + restaurant.setAddress(rs.getString("address")); + restaurant.setContact(rs.getString("contact")); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java new file mode 100644 index 0000000000..3a5187a86c --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java @@ -0,0 +1,135 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Customer; +import io.orkes.example.saga.pojos.Order; + +import java.sql.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.TimeZone; +import java.util.Date; + +public class OrdersDAO extends BaseDAO { + + public OrdersDAO(String url) { + super(url); + } + + public String insertOrder(Order order) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String itemsStr = String.join("", order.getOrderDetails().getItems().toString()); + + String notesStr = null; + + if(!order.getOrderDetails().getNotes().isEmpty()) { + notesStr = String.join("", order.getOrderDetails().getNotes().toString()); + } else { + notesStr = ""; + } + + String sql = "INSERT INTO orders(orderId,customerId,restaurantId,deliveryAddress,createdAt,status) VALUES(?,?,?,?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, order.getOrderId()); + pstmt.setInt(2, order.getCustomer().getId()); + pstmt.setInt(3, order.getRestaurantId()); + pstmt.setString(4, order.getDeliveryAddress()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, order.getStatus().name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + + sql = "INSERT INTO orders_details(orderId,items,notes) VALUES(?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, order.getOrderId()); + pstmt.setString(2, itemsStr); + pstmt.setString(3, notesStr); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + + return ""; + } + + public void updateOrder(Order order) { + String sql = "UPDATE orders SET restaurantId=?,deliveryAddress=?,status=? WHERE orderId=?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, order.getRestaurantId()); + pstmt.setString(2, order.getDeliveryAddress()); + pstmt.setString(3, order.getStatus().name()); + pstmt.setString(4, order.getOrderId()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readOrder(String orderId, Order order) { + String sql = "SELECT orderId, customerId, restaurantId, deliveryAddress, createdAt, status FROM orders WHERE orderId = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, orderId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + order.setOrderId(rs.getString("orderId")); + Customer customer = new Customer(); + customer.setId(rs.getInt("customerId")); + order.setCustomer(customer); + order.setRestaurantId(rs.getInt("restaurantId")); + order.setDeliveryAddress(rs.getString("deliveryAddress")); + order.setCreatedAt(rs.getLong("createdAt")); + order.setStatus(Order.Status.valueOf(rs.getString("status"))); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public int insertCustomer(Customer customer) { + int id = 0; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM customers WHERE email = ?")) { + pstmt.setString(1, customer.getEmail()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) { + id = rs.getInt("id"); + } + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + + if (id > 0) { + return id; + } + + String sql = "INSERT INTO customers(email,name,contact) VALUES(?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, customer.getEmail()); + pstmt.setString(2, customer.getName()); + pstmt.setString(3, customer.getContact()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM customers WHERE email = ?")) { + pstmt.setString(1, customer.getEmail()); + ResultSet rs = pstmt.executeQuery(); + id = rs.getInt("id"); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return id; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java new file mode 100644 index 0000000000..a56d32dbf0 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java @@ -0,0 +1,65 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Payment; + +import java.sql.*; +import java.util.Date; + +public class PaymentsDAO extends BaseDAO { + + public PaymentsDAO(String url) { + super(url); + } + + public String insertPayment(Payment payment) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String sql = "INSERT INTO payments(paymentId, orderId, amount, method, createdAt, status) VALUES(?,?,?,?,?,?);"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, payment.getPaymentId()); + pstmt.setString(2, payment.getOrderId()); + pstmt.setDouble(3, payment.getAmount()); + pstmt.setString(4, payment.getPaymentMethod().toString()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, payment.getStatus().name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + return ""; + } + + public void updatePaymentStatus(Payment payment) { + String sql = "UPDATE payments SET status=? WHERE paymentId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, payment.getStatus().name()); + pstmt.setString(2, payment.getPaymentId()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readPayment(String orderId, Payment payment) { + String sql = "SELECT paymentId, orderId, amount, method, createdAt, status FROM payments WHERE orderId = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, orderId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + payment.setPaymentId(rs.getString("paymentId")); + payment.setOrderId(rs.getString("orderId")); + payment.setAmount(rs.getDouble("amount")); + payment.setCreatedAt(rs.getLong("createdAt")); + payment.setStatus(Payment.Status.valueOf(rs.getString("status"))); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java new file mode 100644 index 0000000000..f0597c553e --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java @@ -0,0 +1,75 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Driver; +import io.orkes.example.saga.pojos.Shipment; + +import java.sql.*; +import java.util.Date; + +public class ShipmentDAO extends BaseDAO { + + public ShipmentDAO(String url) { + super(url); + } + + public boolean insertShipment(Shipment shipment) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String sql = "INSERT INTO shipments(orderId,driverId,address,instructions,createdAt,status) VALUES(?,?,?,?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, shipment.getOrderId()); + pstmt.setInt(2, shipment.getDriverId()); + pstmt.setString(3, shipment.getDeliveryAddress()); + pstmt.setString(4, shipment.getDeliveryInstructions()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, Shipment.Status.SCHEDULED.name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return false; + } + return true; + } + public void cancelShipment(String orderId) { + String sql = "UPDATE shipments SET status=? WHERE orderId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, Shipment.Status.CANCELED.name()); + pstmt.setString(2, orderId); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void confirmShipment(String orderId) { + String sql = "UPDATE shipments SET status=? WHERE orderId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, Shipment.Status.CONFIRMED.name()); + pstmt.setString(2, orderId); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readDriver(int driverId, Driver driver) { + String sql = "SELECT name, contact FROM drivers WHERE id = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, driverId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + driver.setId(driverId); + driver.setName(rs.getString("name")); + driver.setContact(rs.getString("contact")); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java new file mode 100644 index 0000000000..84094259cf --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java @@ -0,0 +1,8 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class CancelRequest { + private String orderId; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java new file mode 100644 index 0000000000..35a776bfdd --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + + +import lombok.Data; +import java.util.ArrayList; + +@Data +public class CheckInventoryRequest { + private int restaurantId; + private ArrayList items; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java new file mode 100644 index 0000000000..b0c6216016 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Customer { + private int id; + private String email; + private String name; + private String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java new file mode 100644 index 0000000000..ed8df6a4f9 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java @@ -0,0 +1,10 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Driver { + int id; + String name; + String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java new file mode 100644 index 0000000000..31c39c0f9a --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class DriverNotificationRequest { + int driverId; + String dropOff; + String pickUp; + String orderId; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java new file mode 100644 index 0000000000..28d031aba3 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java @@ -0,0 +1,19 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.ArrayList; + +@Data +public class FoodDeliveryRequest { + private String customerEmail; + private String customerName; + private String customerContact; + private int restaurantId; + private ArrayList foodItems; + private ArrayList additionalNotes; + private String address; + private String deliveryInstructions; + private double paymentAmount; + private Object paymentMethod; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java new file mode 100644 index 0000000000..1a20c5f8ec --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class FoodItem { + private String item; + private int quantity; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java new file mode 100644 index 0000000000..7b68519196 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java @@ -0,0 +1,24 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.EnumMap; + +@Data +public class Order { + + public enum Status { + PENDING, + ASSIGNED, + CONFIRMED, + CANCELLED + } + + private String orderId; + private Customer customer; + private int restaurantId; + private String deliveryAddress; + private long createdAt; + private Status status; + private OrderDetails orderDetails; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java new file mode 100644 index 0000000000..9b55933d02 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import java.util.ArrayList; + +@Data +public class OrderDetails { + private String orderId; + private ArrayList items; + private ArrayList notes; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java new file mode 100644 index 0000000000..ab3c28b543 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java @@ -0,0 +1,18 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.ArrayList; + +@Data +public class OrderRequest { + private String OrderRequestId; + private String customerEmail; + private String customerName; + private String customerContact; + private int restaurantId; + private ArrayList items; + private ArrayList notes; + private String deliveryAddress; + private String deliveryInstructions; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java new file mode 100644 index 0000000000..02a9d846ea --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java @@ -0,0 +1,20 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Payment { + public enum Status { + PENDING, + FAILED, + SUCCESSFUL, + CANCELED + } + private String paymentId; + private String orderId; + private double amount; + private PaymentMethod paymentMethod; + private Status status; + private long createdAt; + private String errorMsg; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java new file mode 100644 index 0000000000..a0679aaeed --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java @@ -0,0 +1,12 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class PaymentDetails { + private String number; + private String expiry; + private int cvv; +} \ No newline at end of file diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java new file mode 100644 index 0000000000..ada06e5bec --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class PaymentMethod { + private String type; + private PaymentDetails details; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java new file mode 100644 index 0000000000..b0d2590c7b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class PaymentRequest { + private String orderId; + private int customerId; + private float amount; + private PaymentMethod method; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java new file mode 100644 index 0000000000..aaa9cf8cb3 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Restaurant { + int id; + String name; + String address; + String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java new file mode 100644 index 0000000000..3a6a960e46 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java @@ -0,0 +1,20 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Shipment { + public enum Status { + SCHEDULED, + CONFIRMED, + DELIVERED, + CANCELED + } + private int id; + private String orderId; + private int driverId; + private String deliveryAddress; + private String deliveryInstructions; + private long createdAt; + private String status; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java new file mode 100644 index 0000000000..296442f846 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java @@ -0,0 +1,10 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class ShippingRequest { + private String orderId; + private String deliveryAddress; + private String deliveryInstructions; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java new file mode 100644 index 0000000000..bd750ae47b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java @@ -0,0 +1,23 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.InventoryDAO; +import io.orkes.example.saga.pojos.FoodItem; +import io.orkes.example.saga.pojos.Restaurant; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Objects; + +@Slf4j +public class InventoryService { + + private static final InventoryDAO inventoryDAO = new InventoryDAO("jdbc:sqlite:food_delivery.db"); + + public static boolean checkAvailability(int restaurantId, ArrayList items) { + Restaurant restaurant = new Restaurant(); + restaurant.setId(restaurantId); + restaurant.setName(""); + inventoryDAO.readRestaurant(restaurantId, restaurant); + return !Objects.equals(restaurant.getName(), ""); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java new file mode 100644 index 0000000000..d42d999641 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java @@ -0,0 +1,72 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.OrdersDAO; +import io.orkes.example.saga.pojos.Customer; +import io.orkes.example.saga.pojos.Order; +import io.orkes.example.saga.pojos.OrderDetails; +import io.orkes.example.saga.pojos.OrderRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Slf4j +@AllArgsConstructor +@Service +public class OrderService { + + private static final OrdersDAO ORDERS_DAO = new OrdersDAO("jdbc:sqlite:food_delivery.db"); + + public static String createOrder(OrderRequest orderRequest) { + UUID uuid = UUID.randomUUID(); + String uuidAsString = uuid.toString(); + + Order order = new Order(); + order.setOrderId(uuidAsString); + + Customer customer = new Customer(); + customer.setEmail(orderRequest.getCustomerEmail()); + customer.setName(orderRequest.getCustomerName()); + customer.setContact(orderRequest.getCustomerContact()); + customer.setId(ORDERS_DAO.insertCustomer(customer)); + + log.info("Upsert customer record in DB with id: {}", customer.getId()); + + order.setCustomer(customer); + order.setRestaurantId(orderRequest.getRestaurantId()); + order.setDeliveryAddress(orderRequest.getDeliveryAddress()); + order.setStatus(Order.Status.PENDING); + + OrderDetails orderDetails = new OrderDetails(); + orderDetails.setOrderId(uuidAsString); + orderDetails.setItems(orderRequest.getItems()); + orderDetails.setNotes(orderRequest.getNotes()); + + order.setOrderDetails(orderDetails); + + String error = ORDERS_DAO.insertOrder(order); + + if (error.isEmpty()) { + log.info("Created order with id: {}", order.getOrderId()); + } + else { + log.error("Order creation failure: {}", error); + return null; + } + + return uuidAsString; + } + + public static Order getOrder(String orderId) { + Order order = new Order(); + ORDERS_DAO.readOrder(orderId, order); + return order; + } + + public static void cancelOrder(Order order) { + order.setStatus(Order.Status.CANCELLED); + log.info("Cancelling order {}", order.getOrderId()); + ORDERS_DAO.updateOrder(order); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java new file mode 100644 index 0000000000..0693586e6f --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java @@ -0,0 +1,85 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.PaymentsDAO; +import io.orkes.example.saga.pojos.Payment; +import io.orkes.example.saga.pojos.PaymentDetails; +import io.orkes.example.saga.pojos.PaymentMethod; +import io.orkes.example.saga.pojos.PaymentRequest; +import lombok.extern.slf4j.Slf4j; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; +import java.util.UUID; + +@Slf4j +public class PaymentService { + + private static final PaymentsDAO paymentsDAO = new PaymentsDAO("jdbc:sqlite:food_delivery.db"); + + public static Payment createPayment(PaymentRequest paymentRequest) { + UUID uuid = UUID.randomUUID(); + String uuidAsString = uuid.toString(); + + Payment payment = new Payment(); + payment.setPaymentId(uuidAsString); + payment.setOrderId(paymentRequest.getOrderId()); + payment.setAmount(paymentRequest.getAmount()); + payment.setPaymentMethod(paymentRequest.getMethod()); + payment.setStatus(Payment.Status.PENDING); + + // Check if returned error is non-empty, i.e failure + if (!paymentsDAO.insertPayment(payment).isEmpty()) { + log.error("Failed to process payment for order {}", paymentRequest.getOrderId()); + payment.setErrorMsg("Payment creation failure"); + payment.setStatus(Payment.Status.FAILED); + } + else { + if(makePayment(payment)) { + payment.setStatus(Payment.Status.SUCCESSFUL); + } else { + payment.setStatus(Payment.Status.FAILED); + } + } + + // Record final status + paymentsDAO.updatePaymentStatus(payment); + return payment; + } + + public static void cancelPayment(String orderId) { + // Cancel Payment in DB + Payment payment = new Payment(); + paymentsDAO.readPayment(orderId, payment); + payment.setStatus(Payment.Status.CANCELED); + paymentsDAO.updatePaymentStatus(payment); + } + + private static boolean makePayment(Payment payment) { + if (Objects.equals(payment.getPaymentMethod().getType(), "Credit Card")) { + PaymentDetails details = payment.getPaymentMethod().getDetails(); + + DateFormat dateFormat= new SimpleDateFormat("MM/yyyy"); + Date expiry = new Date(); + + try { + expiry = dateFormat.parse(details.getExpiry()); + } catch (ParseException e) { + payment.setErrorMsg("Invalid expiry date:" + details.getExpiry()); + return false; + } + + Date today = new Date(); + if (today.getTime() > expiry.getTime()) { + payment.setErrorMsg("Expired payment method:" + details.getExpiry()); + return false; + } + + } + // Ideally an async call would be made with a callback + // But, we're skipping that and assuming payment went through + return true; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java new file mode 100644 index 0000000000..059b1cb36f --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java @@ -0,0 +1,64 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.ShipmentDAO; +import io.orkes.example.saga.pojos.Driver; +import io.orkes.example.saga.pojos.Shipment; +import io.orkes.example.saga.pojos.ShippingRequest; +import lombok.extern.slf4j.Slf4j; + +import java.util.Random; + +@Slf4j +public class ShipmentService { + + private static final ShipmentDAO shipmentDAO = new ShipmentDAO("jdbc:sqlite:food_delivery.db"); + + public static int createShipment(ShippingRequest shippingRequest) { + String orderId = shippingRequest.getOrderId(); + + Shipment shipment = new Shipment(); + shipment.setOrderId(orderId); + shipment.setDeliveryAddress(shippingRequest.getDeliveryAddress()); + shipment.setDeliveryInstructions(shippingRequest.getDeliveryInstructions()); + + int driverId = findDriver(); + shipment.setDriverId(driverId); + + if (!shipmentDAO.insertShipment(shipment)) { + log.error("Shipment creation for order {} failed.", orderId); + return 0; + } + + Driver driver = new Driver(); + driver.setName(""); + shipmentDAO.readDriver(driverId, driver); + + if (driver.getName().isBlank()) { + log.error("Shipment creation for order {} failed as driver in the area is not available.", orderId); + shipmentDAO.cancelShipment(orderId); + return 0; + } + else { + log.info("Assigned driver {} to order with id: {}", driverId, orderId); + shipmentDAO.confirmShipment(orderId); + } + + return driverId; + } + + public static void cancelDelivery(String orderId) { + shipmentDAO.cancelShipment(orderId); + } + + private static int findDriver() { + Random random = new Random(); + int driverId = 0; + int counter = 0; + while (counter < 10) { + driverId = random.nextInt(4); + if(driverId !=0) break; + counter += 1; + } + return driverId; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java new file mode 100644 index 0000000000..d3914aecc8 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java @@ -0,0 +1,61 @@ +package io.orkes.example.saga.service; + +import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; +import io.orkes.conductor.client.WorkflowClient; +import io.orkes.example.saga.pojos.FoodDeliveryRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@AllArgsConstructor +@Service +public class WorkflowService { + + private final WorkflowClient workflowClient; + private final Environment environment; + + public Map startFoodDeliveryWorkflow(FoodDeliveryRequest foodDeliveryRequest) { + StartWorkflowRequest request = new StartWorkflowRequest(); + request.setName("FoodDeliveryWorkflow"); + request.setVersion(1); + request.setCorrelationId("api-triggered"); + + String TASK_DOMAIN_PROPERTY = "conductor.worker.all.domain"; + String domain = environment.getProperty(TASK_DOMAIN_PROPERTY, String.class, ""); + + if (!domain.isEmpty()) { + Map taskToDomain = new HashMap<>(); + taskToDomain.put("*", domain); + request.setTaskToDomain(taskToDomain); + } + + Map inputData = new HashMap<>(); + inputData.put("customerEmail", foodDeliveryRequest.getCustomerEmail()); + inputData.put("customerName", foodDeliveryRequest.getCustomerName()); + inputData.put("customerContact", foodDeliveryRequest.getCustomerContact()); + inputData.put("restaurantId", foodDeliveryRequest.getRestaurantId()); + inputData.put("foodItems", foodDeliveryRequest.getFoodItems()); + inputData.put("additionalNotes", foodDeliveryRequest.getAdditionalNotes()); + inputData.put("address", foodDeliveryRequest.getAddress()); + inputData.put("deliveryInstructions", foodDeliveryRequest.getDeliveryInstructions()); + inputData.put("paymentAmount", foodDeliveryRequest.getPaymentAmount()); + inputData.put("paymentMethod", foodDeliveryRequest.getPaymentMethod()); + request.setInput(inputData); + + String workflowId = ""; + try { + workflowId = workflowClient.startWorkflow(request); + log.info("Workflow id: {}", workflowId); + } catch (Exception ex) { + ex.printStackTrace(System.out); + return Map.of("error", "Order creation failure", "detail", ex.toString()); + } + + return Map.of("workflowId", workflowId); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java new file mode 100644 index 0000000000..aeb51ddd11 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java @@ -0,0 +1,130 @@ +package io.orkes.example.saga.workers; + +import com.netflix.conductor.common.metadata.tasks.TaskResult; +import com.netflix.conductor.sdk.workflow.task.WorkerTask; +import io.orkes.example.saga.pojos.*; +import io.orkes.example.saga.service.InventoryService; +import io.orkes.example.saga.service.OrderService; +import io.orkes.example.saga.service.PaymentService; +import io.orkes.example.saga.service.ShipmentService; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@AllArgsConstructor +@Component +@ComponentScan(basePackages = {"io.orkes"}) +public class ConductorWorkers { + /** + * Note: Using this setting, up to 5 tasks will run in parallel, with tasks being polled every 200ms + */ + @WorkerTask(value = "order_food", threadCount = 3, pollingInterval = 300) + public TaskResult orderFoodTask(OrderRequest orderRequest) { + String orderId = OrderService.createOrder(orderRequest); + + TaskResult result = new TaskResult(); + Map output = new HashMap<>(); + + if(orderId != null) { + output.put("orderId", orderId); + result.setOutputData(output); + result.setStatus(TaskResult.Status.COMPLETED); + } else { + output.put("orderId", null); + result.setStatus(TaskResult.Status.FAILED); + } + return result; + } + + @WorkerTask(value = "check_inventory", threadCount = 2, pollingInterval = 300) + public TaskResult checkInventoryTask(CheckInventoryRequest checkInventoryRequest) { + int restaurantId = checkInventoryRequest.getRestaurantId(); + ArrayList items = checkInventoryRequest.getItems(); + boolean availability = InventoryService.checkAvailability(restaurantId, items); + + TaskResult result = new TaskResult(); + + if (availability) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + result.setReasonForIncompletion("Restaurant is closed"); + result.setStatus(TaskResult.Status.FAILED_WITH_TERMINAL_ERROR); + } + + return result; + } + + @WorkerTask(value = "make_payment", threadCount = 2, pollingInterval = 300) + public TaskResult makePaymentTask(PaymentRequest paymentRequest) { + TaskResult result = new TaskResult(); + + Payment payment = PaymentService.createPayment(paymentRequest); + Map output = new HashMap<>(); + output.put("orderId", payment.getOrderId()); + output.put("paymentId", payment.getPaymentId()); + output.put("paymentStatus", payment.getStatus().name()); + + if(payment.getStatus() == Payment.Status.SUCCESSFUL) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + output.put("error", payment.getErrorMsg()); + result.setStatus(TaskResult.Status.FAILED_WITH_TERMINAL_ERROR); + } + + result.setOutputData(output); + + return result; + } + + @WorkerTask(value = "ship_food", threadCount = 2, pollingInterval = 300) + public TaskResult shipFoodTask(ShippingRequest shippingRequest) { + TaskResult result = new TaskResult(); + Map output = new HashMap<>(); + int driverId = ShipmentService.createShipment(shippingRequest); + if (driverId != 0) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + result.setStatus(TaskResult.Status.FAILED); + } + return result; + } + + @WorkerTask(value = "notify_driver", threadCount = 2, pollingInterval = 300) + public Map checkForDriverNotifications(DriverNotificationRequest driverNotificationRequest) { + Map result = new HashMap<>(); + return result; + } + + @WorkerTask(value = "notify_customer", threadCount = 2, pollingInterval = 300) + public Map checkForCustomerNotifications(Order order) { + Map result = new HashMap<>(); + return result; + } +// + @WorkerTask(value = "cancel_payment", threadCount = 2, pollingInterval = 300) + public Map cancelPaymentTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + PaymentService.cancelPayment(cancelRequest.getOrderId()); + return result; + } + + @WorkerTask(value = "cancel_delivery", threadCount = 2, pollingInterval = 300) + public Map cancelDeliveryTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + ShipmentService.cancelDelivery(cancelRequest.getOrderId()); + return result; + } + + @WorkerTask(value = "cancel_order", threadCount = 2, pollingInterval = 300) + public Map cancelOrderTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + Order order = OrderService.getOrder(cancelRequest.getOrderId()); + OrderService.cancelOrder(order); + return result; + } + +} diff --git a/microservices-modules/saga-pattern/src/main/resources/application.properties b/microservices-modules/saga-pattern/src/main/resources/application.properties new file mode 100644 index 0000000000..8df5f3e82e --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/resources/application.properties @@ -0,0 +1,32 @@ + +spring.mvc.pathmatch.matching-strategy=ant_path_matcher + +springdoc.swagger-ui.path=/swagger-ui.html + +management.endpoints.enabled-by-default=false +management.endpoint.info.enabled=false + +# Local app server port +server.port=8081 + +# Playground + +# Obtain key and secret by logging into https://play.orkes.io/ +# and navigating to applications menu, create an application and generate key/secret +conductor.server.url=https://play.orkes.io/api +conductor.security.client.key-id= +conductor.security.client.secret= + + +# Task Domain +conductor.worker.all.domain=saga +conductor.worker.all.pollingInterval=22 + + +# DB Setup +spring.jpa.database-platform=com.springboot.sqlite.SQLDialect +spring.jpa.hibernate.ddl-auto=update +spring.datasource.url=jdbc:sqlite:food_delivery.db +spring.datasource.driver-class-name = org.sqlite.JDBC +spring.datasource.username=admin +spring.datasource.password=admin diff --git a/parent-spring-6/pom.xml b/parent-spring-6/pom.xml index 4665030baf..1d0d54d398 100644 --- a/parent-spring-6/pom.xml +++ b/parent-spring-6/pom.xml @@ -35,7 +35,7 @@ - 6.1.2 + 6.1.5 2023.0.0 3.2.1 diff --git a/patterns-modules/enterprise-patterns/pom.xml b/patterns-modules/enterprise-patterns/pom.xml index a3c9da448d..45da43ba6f 100644 --- a/patterns-modules/enterprise-patterns/pom.xml +++ b/patterns-modules/enterprise-patterns/pom.xml @@ -52,6 +52,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} diff --git a/patterns-modules/intercepting-filter/pom.xml b/patterns-modules/intercepting-filter/pom.xml index 60246e7838..949695afed 100644 --- a/patterns-modules/intercepting-filter/pom.xml +++ b/patterns-modules/intercepting-filter/pom.xml @@ -39,6 +39,7 @@ org.eclipse.jetty jetty-maven-plugin + ${jetty-plugin.version} / @@ -50,6 +51,7 @@ 3.3.2 + 11.0.20 \ No newline at end of file diff --git a/patterns-modules/monkey-patching/pom.xml b/patterns-modules/monkey-patching/pom.xml index e7fae87646..1d0146d990 100644 --- a/patterns-modules/monkey-patching/pom.xml +++ b/patterns-modules/monkey-patching/pom.xml @@ -29,7 +29,7 @@ org.springframework.boot spring-boot-starter-aop - 2.7.0 + ${spring-boot.version} @@ -38,7 +38,12 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} + + + 2.7.0 + diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml index dea261adca..d785bc0452 100644 --- a/persistence-modules/core-java-persistence-2/pom.xml +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -87,7 +87,7 @@ 10.2.0.4.0 8.2.0 3.11.11 - 20220320 + 20240303 07.00.00-MS-GA 2.1.214 5.3.29 diff --git a/persistence-modules/hibernate-annotations/README.md b/persistence-modules/hibernate-annotations/README.md index 663c39ea33..446dde9ece 100644 --- a/persistence-modules/hibernate-annotations/README.md +++ b/persistence-modules/hibernate-annotations/README.md @@ -13,3 +13,4 @@ This module contains articles about Annotations used in Hibernate. - [Hibernate @CreationTimestamp and @UpdateTimestamp](https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp) - [Difference Between @JoinColumn and @PrimaryKeyJoinColumn in JPA](https://www.baeldung.com/java-jpa-join-vs-primarykeyjoin) - [A Guide to the @SoftDelete Annotation in Hibernate](https://www.baeldung.com/java-hibernate-softdelete-annotation) +- [@Subselect Annotation in Hibernate](https://www.baeldung.com/hibernate-subselect) diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml index 6f11888643..12a5298e95 100644 --- a/persistence-modules/hibernate-annotations/pom.xml +++ b/persistence-modules/hibernate-annotations/pom.xml @@ -81,6 +81,16 @@ hypersistence-utils-hibernate-60 ${hypersistance-utils-hibernate-60.version} + + org.liquibase + liquibase-core + ${liquibase-core.version} + + + org.projectlombok + lombok + ${lombok.version} + @@ -91,6 +101,8 @@ true 9.0.0.M26 3.3.1 + 1.18.30 + 4.24.0 \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java index 99410e1f76..0bf03e3fee 100644 --- a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java @@ -4,6 +4,7 @@ import com.baeldung.hibernate.oneToMany.model.Cart; import com.baeldung.hibernate.oneToMany.model.CartOIO; import com.baeldung.hibernate.oneToMany.model.Item; import com.baeldung.hibernate.oneToMany.model.ItemOIO; +import com.baeldung.hibernate.subselect.RuntimeConfiguration; import org.hibernate.SessionFactory; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; @@ -38,6 +39,7 @@ public class HibernateAnnotationUtil { .addAnnotatedClass(CartOIO.class) .addAnnotatedClass(Item.class) .addAnnotatedClass(ItemOIO.class) + .addAnnotatedClass(RuntimeConfiguration.class) .buildMetadata(); return metadata.buildSessionFactory(); diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java new file mode 100644 index 0000000000..0f995bfe03 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java @@ -0,0 +1,43 @@ +package com.baeldung.hibernate.subselect; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import java.time.Instant; +import lombok.Data; +import lombok.experimental.Accessors; +import org.hibernate.annotations.Subselect; + +@Data +@Accessors(chain = true) +@Entity +// language=sql +@Subselect(value = + "SELECT\n" + + " ss.id,\n" + + " ss.attr_key,\n" + + " ss.val,\n" + + " ss.created_at\n" + + " FROM system_settings AS ss\n" + + " INNER JOIN (\n" + + " SELECT\n" + + " ss2.attr_key as k2,\n" + + " MAX(ss2.created_at) as ca2\n" + + " FROM system_settings ss2\n" + + " GROUP BY ss2.attr_key\n" + + " ) AS t ON t.k2 = ss.attr_key AND t.ca2 = ss.created_at\n" + + " WHERE ss.type = 'SYSTEM' AND ss.active IS TRUE\n") +public class RuntimeConfiguration { + + @Id + private Long id; + + @Column(name = "attr_key") + private String key; + + @Column(name = "val") + private String value; + + @Column(name = "created_at") + private Instant createdAt; +} diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml new file mode 100644 index 0000000000..5970821ccd --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + splitting.enabled + true + true + SYSTEM + + + + + 2 + splitting.enabled + false + false + SYSTEM + + + + + 3 + redelivery.enabled + false + true + ORDER + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml new file mode 100644 index 0000000000..ba16dc7b8b --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java new file mode 100644 index 0000000000..074468ca37 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.hibernate.subselect; + +import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil; +import jakarta.persistence.criteria.Root; +import liquibase.Contexts; +import liquibase.LabelExpression; +import liquibase.Liquibase; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.ClassLoaderResourceAccessor; +import org.hibernate.Session; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class SubselectIntegrationTest { + + @BeforeAll + static void setUp() { + Session currentSession = HibernateAnnotationUtil.getSessionFactory().getCurrentSession(); + currentSession.beginTransaction(); + + currentSession.doWork(it -> { + Liquibase liquibase; + try { + liquibase = new Liquibase( + "migrations/master.xml", + new ClassLoaderResourceAccessor(), + DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(it)) + ); + liquibase.update(new Contexts(), new LabelExpression(),true); + } catch (LiquibaseException e) { + throw new RuntimeException(e); + } + }); + + currentSession.getTransaction().commit(); + } + + @Test + void givenEntityMarkedWithSubselect_whenSelectingRuntimeConfigByKey_thenSelectedSuccessfully() { + String key = "splitting.enabled"; + Session entityManager = HibernateAnnotationUtil.getSessionFactory().getCurrentSession(); + + entityManager.beginTransaction(); + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + CriteriaQuery query = criteriaBuilder.createQuery(RuntimeConfiguration.class); + + Root root = query.from(RuntimeConfiguration.class); + + RuntimeConfiguration configurationParameter = entityManager.createQuery( + query.select(root).where(criteriaBuilder.equal(root.get("key"), key)) + ).getSingleResult(); + + entityManager.getTransaction().commit(); + + Assertions.assertThat(configurationParameter.getValue()).isEqualTo("true"); + } +} + diff --git a/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java b/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java index 921459ac46..41924ad33f 100644 --- a/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java +++ b/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java @@ -9,7 +9,9 @@ import static org.junit.Assert.assertSame; import jakarta.persistence.PersistenceException; +import org.h2.tools.RunScript; import org.hibernate.HibernateException; +import org.hibernate.ReplicationMode; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; @@ -24,35 +26,58 @@ import org.junit.Test; import com.baeldung.persistence.model.Person; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.sql.Connection; +import java.sql.DriverManager; + /** * Testing specific implementation details for different methods: - * persist, save, merge, update, saveOrUpdate. + * persist, save, merge, update, saveOrUpdate, refresh, replicate */ public class SaveMethodsIntegrationTest { - private static SessionFactory sessionFactory; + private static SessionFactory sessionFactory1; - private Session session; + private static SessionFactory sessionFactory2; + + private Session session1; + + private Session session2; private boolean doNotCommit = false; - @BeforeClass - public static void beforeTests() { + private static SessionFactory createSessionFactoryAndInitializeDBs(String dbUrl) throws Exception { Configuration configuration = new Configuration().addAnnotatedClass(Person.class) - .setProperty("hibernate.dialect", HSQLDialect.class.getName()) - .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) - .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") - .setProperty("hibernate.connection.username", "sa") - .setProperty("hibernate.connection.password", "") - .setProperty("hibernate.hbm2ddl.auto", "update"); + .setProperty("hibernate.dialect", HSQLDialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", dbUrl) + .setProperty("hibernate.connection.username", "sa") + .setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + Connection connection = DriverManager.getConnection(dbUrl, "sa", ""); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()) - .build(); - sessionFactory = configuration.buildSessionFactory(serviceRegistry); + .build(); + SessionFactory sf = configuration.buildSessionFactory(serviceRegistry); + try (InputStream h2InitStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("h2-trigger.sql")) { + assert h2InitStream != null; + try (InputStreamReader h2InitReader = new InputStreamReader(h2InitStream)) { + RunScript.execute(connection, h2InitReader); + } + } + return sf; + } + @BeforeClass + public static void beforeTests() throws Exception{ + sessionFactory1 = createSessionFactoryAndInitializeDBs("jdbc:hsqldb:mem:test"); + sessionFactory2 = createSessionFactoryAndInitializeDBs("jdbc:hsqldb:mem:test2"); + } @Before - public void setUp() { - session = sessionFactory.openSession(); - session.beginTransaction(); + public void setUp() throws Exception { + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); + doNotCommit = false; } @@ -61,16 +86,16 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.persist(person); + session1.persist(person); - session.getTransaction() - .commit(); - session.close(); + session1.getTransaction() + .commit(); + session1.close(); - session = sessionFactory.openSession(); - session.beginTransaction(); + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); - assertNotNull(session.get(Person.class, person.getId())); + assertNotNull(session1.get(Person.class, person.getId())); } @@ -80,10 +105,10 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.persist(person); + session1.persist(person); Long id1 = person.getId(); - session.persist(person); + session1.persist(person); Long id2 = person.getId(); assertEquals(id1, id2); @@ -93,13 +118,13 @@ public class SaveMethodsIntegrationTest { public void whenPersistDetached_thenThrowsException() { doNotCommit = true; - + Person person = new Person(); person.setName("John"); - session.persist(person); - session.evict(person); - - session.persist(person); + session1.persist(person); + session1.evict(person); + + session1.persist(person); } @Test @@ -107,12 +132,12 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); - session.flush(); - session.evict(person); + session1.save(person); + session1.flush(); + session1.evict(person); person.setName("Mary"); - Person mergedPerson = (Person) session.merge(person); + Person mergedPerson = (Person) session1.merge(person); assertNotSame(person, mergedPerson); assertEquals("Mary", mergedPerson.getName()); @@ -127,20 +152,20 @@ public class SaveMethodsIntegrationTest { assertNull(person.getId()); - Long id = (Long) session.save(person); + Long id = (Long) session1.save(person); assertNotNull(id); - session.getTransaction() - .commit(); - session.close(); + session1.getTransaction() + .commit(); + session1.close(); assertEquals(id, person.getId()); - session = sessionFactory.openSession(); - session.beginTransaction(); + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); - assertNotNull(session.get(Person.class, person.getId())); + assertNotNull(session1.get(Person.class, person.getId())); } @@ -149,8 +174,8 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - Long id1 = (Long) session.save(person); - Long id2 = (Long) session.save(person); + Long id1 = (Long) session1.save(person); + Long id2 = (Long) session1.save(person); assertEquals(id1, id2); } @@ -160,10 +185,10 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - Long id1 = (Long) session.save(person); - session.evict(person); + Long id1 = (Long) session1.save(person); + session1.evict(person); - Long id2 = (Long) session.save(person); + Long id2 = (Long) session1.save(person); assertNotEquals(id1, id2); } @@ -173,11 +198,11 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - Person mergedPerson = (Person) session.merge(person); + Person mergedPerson = (Person) session1.merge(person); - session.getTransaction() - .commit(); - session.beginTransaction(); + session1.getTransaction() + .commit(); + session1.beginTransaction(); assertNotNull(person.getId()); assertNotNull(mergedPerson.getId()); @@ -189,9 +214,9 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); + session1.save(person); - Person mergedPerson = (Person) session.merge(person); + Person mergedPerson = (Person) session1.merge(person); assertSame(person, mergedPerson); @@ -202,11 +227,11 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); - session.evict(person); + session1.save(person); + session1.evict(person); person.setName("Mary"); - session.update(person); + session1.update(person); assertEquals("Mary", person.getName()); } @@ -216,7 +241,7 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.update(person); + session1.update(person); } @@ -225,9 +250,9 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); + session1.save(person); - session.update(person); + session1.update(person); } @@ -236,11 +261,11 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); - session.evict(person); + session1.save(person); + session1.evict(person); person.setName("Mary"); - session.saveOrUpdate(person); + session1.saveOrUpdate(person); assertEquals("Mary", person.getName()); } @@ -250,16 +275,75 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.saveOrUpdate(person); + session1.saveOrUpdate(person); - session.getTransaction() - .commit(); - session.close(); + session1.getTransaction() + .commit(); + session1.close(); - session = sessionFactory.openSession(); - session.beginTransaction(); + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); - assertNotNull(session.get(Person.class, person.getId())); + assertNotNull(session1.get(Person.class, person.getId())); + + } + + @Test + public void whenSaveAndTriggerUpdatedAndRefresh_thenRefreshPersistentEntity() { + + Person person = new Person(); + person.setName("Zeeshan Arif"); + session1.persist(person); + session1.getTransaction() + .commit(); + session1.close(); + + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); + session1.refresh(person); + session1.getTransaction() + .commit(); + session1.close(); + + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); + assertEquals(person.getName(), "Neymar Santos"); + + } + + @Test + public void whenReplicate_thenRefreshPersistentEntity() { + + Person p = new Person(); + p.setName("Ronaldinho Gaucho"); + session1.persist(p); + session1.getTransaction() + .commit(); + session1.close(); + + Session session2 = sessionFactory2.openSession(); + session2.beginTransaction(); + session2.replicate(p, ReplicationMode.LATEST_VERSION); + session2.getTransaction() + .commit(); + session2.close(); + + session2 = sessionFactory2.openSession(); + session2.beginTransaction(); + Person actual = session2.get(Person.class, p.getId()); + session2.getTransaction().commit(); + session2.close(); + + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); + Person expected = session1.get(Person.class, p.getId()); + session1.getTransaction().commit(); + session1.close(); + + session1 = sessionFactory1.openSession(); + session1.beginTransaction(); + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getName(), actual.getName()); } @@ -268,24 +352,25 @@ public class SaveMethodsIntegrationTest { Person person = new Person(); person.setName("John"); - session.save(person); + session1.save(person); - session.saveOrUpdate(person); + session1.saveOrUpdate(person); } @After public void tearDown() { if (!doNotCommit) { - session.getTransaction() - .commit(); + session1.getTransaction() + .commit(); } - session.close(); + session1.close(); } @AfterClass public static void afterTests() { - sessionFactory.close(); + sessionFactory1.close(); + sessionFactory2.close(); } } diff --git a/persistence-modules/hibernate-enterprise/src/test/resources/h2-trigger.sql b/persistence-modules/hibernate-enterprise/src/test/resources/h2-trigger.sql new file mode 100644 index 0000000000..a54b5c5003 --- /dev/null +++ b/persistence-modules/hibernate-enterprise/src/test/resources/h2-trigger.sql @@ -0,0 +1,5 @@ +CREATE TRIGGER IF NOT EXISTS TGR_UpdatePersonName AFTER INSERT +ON Person FOR EACH ROW UPDATE PERSON SET NAME = 'Neymar Santos' where NAME = 'Zeeshan Arif' + + + diff --git a/persistence-modules/hibernate-jpa/README.md b/persistence-modules/hibernate-jpa/README.md index 5599140732..feab5f4d9a 100644 --- a/persistence-modules/hibernate-jpa/README.md +++ b/persistence-modules/hibernate-jpa/README.md @@ -13,4 +13,5 @@ This module contains articles specific to use of Hibernate as a JPA implementati - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) - [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) -- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) \ No newline at end of file +- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) +- [The @Struct Annotation Type in Hibernate – Structured User-Defined Types](https://www.baeldung.com/java-hibernate-struct-annotation) diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java new file mode 100644 index 0000000000..419c47791a --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java @@ -0,0 +1,51 @@ +package com.baeldung.hibernate.struct.entities; + +import jakarta.persistence.*; + +@Entity +public class StructDepartment { + @Id + @GeneratedValue + private Integer id; + + @Column + private String departmentName; + + @Embedded + @Column + private StructManager manager; + + @Override + public String toString() { + return "Department{" + + "id=" + id + + ", departmentName='" + departmentName + '\'' + + ", manager=" + manager + + '}'; + } + + public StructDepartment(String departmentName, StructManager manager) { + this.departmentName = departmentName; + this.manager = manager; + } + + public Integer getId() { + return id; + } + + public String getDepartmentName() { + return departmentName; + } + + public void setDepartmentName(String departmentName) { + this.departmentName = departmentName; + } + + public StructManager getManager() { + return manager; + } + + public void setManager(StructManager manager) { + this.manager = manager; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java new file mode 100644 index 0000000000..10595ecc55 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java @@ -0,0 +1,52 @@ +package com.baeldung.hibernate.struct.entities; +import jakarta.persistence.Embeddable; +import org.hibernate.annotations.Struct; + +import java.io.Serializable; + +@Embeddable +@Struct(name = "Department_Manager_Type", attributes = {"firstName", "lastName", "qualification"}) +public class StructManager implements Serializable { + private String firstName; + private String lastName; + private String qualification; + + @Override + public String toString() { + return "Manager{" + + "firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", qualification='" + qualification + '\'' + + '}'; + } + + public StructManager(String firstName, String lastName, String qualification) { + this.firstName = firstName; + this.lastName = lastName; + this.qualification = qualification; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getQualification() { + return qualification; + } + + public void setQualification(String qualification) { + this.qualification = qualification; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java new file mode 100644 index 0000000000..a836fe0de1 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java @@ -0,0 +1,101 @@ +package com.baeldung.hibernate.struct; + +import com.baeldung.hibernate.struct.entities.StructDepartment; +import com.baeldung.hibernate.struct.entities.StructManager; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateStructUnitTest { + + private Session session; + private Transaction transaction; + + public static SessionFactory getSessionFactoryByProperties(Properties properties) throws IOException { + ServiceRegistry serviceRegistry = configureServiceRegistry(properties); + return makeSessionFactory(serviceRegistry); + } + + private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addPackage("com.baeldung.hibernate.struct.entities"); + metadataSources.addAnnotatedClass(StructDepartment.class); + metadataSources.addAnnotatedClass(StructManager.class); + + Metadata metadata = metadataSources.getMetadataBuilder() + .build(); + + return metadata.getSessionFactoryBuilder() + .build(); + + } + private static ServiceRegistry configureServiceRegistry(Properties properties) throws IOException { + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + public static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate-derby.properties")); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } + + private static ServiceRegistry configureServiceRegistry() throws IOException { + return configureServiceRegistry(getProperties()); + } + private static String PROPERTY_FILE_NAME; + public static SessionFactory getSessionFactory(String propertyFileName) throws IOException { + PROPERTY_FILE_NAME = propertyFileName; + ServiceRegistry serviceRegistry = configureServiceRegistry(); + return makeSessionFactory(serviceRegistry); + } + @Before + public void setUp() throws IOException { + session = getSessionFactory("hibernate-derby.properties") + .openSession(); + transaction = session.beginTransaction(); + + transaction.commit(); + transaction = session.beginTransaction(); + } + + @After + public void tearDown() { + transaction.rollback(); + session.close(); + } + + + +/* This unit test is for reference only because the Hibernate dialect for + Apache Derby database does not support @Struct annotation. + + @Test + public void givenSaveDepartmentObject_ThenManagerUDTExists() { + StructDepartment d = new StructDepartment("Information Technology" + , new StructManager("Zeeshan", "Arif", "Qualified")); + + session.persist(d); + session.flush(); + session.clear(); + + }*/ +} diff --git a/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties new file mode 100644 index 0000000000..72256d1687 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties @@ -0,0 +1,17 @@ +hibernate.connection.driver_class=org.apache.derby.jdbc.EmbeddedDriver +hibernate.connection.url=jdbc:derby:db/derby.dbfile;create=true +hibernate.connection.username= +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.DerbyDialect + +# enable to see Hibernate generated SQL +hibernate.show_sql=false + +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 diff --git a/persistence-modules/hibernate-queries/README.md b/persistence-modules/hibernate-queries/README.md index 9e6c52d6dc..60a84de779 100644 --- a/persistence-modules/hibernate-queries/README.md +++ b/persistence-modules/hibernate-queries/README.md @@ -13,3 +13,4 @@ This module contains articles about use of Queries in Hibernate. - [Distinct Queries in HQL](https://www.baeldung.com/java-hql-distinct) - [JPA and Hibernate – Criteria vs. JPQL vs. HQL Query](https://www.baeldung.com/jpql-hql-criteria-query) - [Database Keywords as Columns in Hibernate Entities](https://www.baeldung.com/java-hibernate-db-keywords-as-columns) +- [Get List of Entity From Database in Hibernate](https://www.baeldung.com/java-hibernate-fetch-entity-list) diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java new file mode 100644 index 0000000000..62a31dd344 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java @@ -0,0 +1,40 @@ +package com.baeldung.hibernate.listentity.entity; + +import java.util.List; +import jakarta.persistence.*; + +@Entity +public class Department { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @OneToMany(mappedBy = "department", fetch = FetchType.EAGER) + private List employees; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java new file mode 100644 index 0000000000..6b4b0c56b1 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.listentity.entity; + +import jakarta.persistence.*; + +@Entity +@NamedQuery(name = "findAllEmployees", query = "SELECT e FROM Employee e") +@NamedQuery(name = "findEmployeesByDepartment", query = "SELECT e FROM Employee e WHERE e.department = :department ORDER BY e.lastName ASC") +public class Employee { + + @Id + @GeneratedValue + private Long id; + + private String lastName; + + private String department; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } +} diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java new file mode 100644 index 0000000000..b336fb1691 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java @@ -0,0 +1,88 @@ +package com.baeldung.hibernate.listentity.service; + +import java.util.Collections; +import java.util.List; + +import jakarta.persistence.*; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + +import org.springframework.stereotype.Service; + +import com.baeldung.hibernate.listentity.entity.Department; +import com.baeldung.hibernate.listentity.entity.Employee; + +@Service +public class EmployeeService { + + @PersistenceContext + private EntityManager entityManager; + + public List getAllEmployeesUsingJPQL() { + String jpqlQuery = "SELECT e FROM Employee e"; + Query query = entityManager.createQuery(jpqlQuery, Employee.class); + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingJPQL() { + String jpqlQuery = "SELECT e FROM Employee e WHERE e.department = 'Engineering' ORDER BY e.lastName ASC"; + Query query = entityManager.createQuery(jpqlQuery, Employee.class); + + return query.getResultList(); + } + + public List getAllEmployeesUsingNamedQuery() { + Query query = entityManager.createNamedQuery("findAllEmployees", Employee.class); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingNamedQuery(String department) { + Query query = entityManager.createNamedQuery("findEmployeesByDepartment", Employee.class); + query.setParameter("department", department); + + return query.getResultList(); + } + + public List getAllEmployeesUsingCriteriaAPI() { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class); + Root employeeRoot = criteriaQuery.from(Employee.class); + + criteriaQuery.select(employeeRoot); + Query query = entityManager.createQuery(criteriaQuery); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingCriteriaAPI(String department) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class); + Root employeeRoot = criteriaQuery.from(Employee.class); + Predicate departmentPredicate = criteriaBuilder.equal(employeeRoot.get("department"), department); + Path sortByPath = employeeRoot.get("lastName"); + criteriaQuery.orderBy(criteriaBuilder.asc(sortByPath)); + criteriaQuery.select(employeeRoot) + .where(departmentPredicate); + Query query = entityManager.createQuery(criteriaQuery); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingOneToManyAnnotations(String departmentName) { + try { + // Retrieve the department by its name + Department department = entityManager.createQuery("SELECT d FROM Department d WHERE d.name = :name", Department.class) + .setParameter("name", departmentName) + .getSingleResult(); + + // Return the list of employees associated with the department + return department.getEmployees(); + } catch (NoResultException e) { + return Collections.emptyList(); + } + } +} diff --git a/spring-boot-modules/spring-caching/src/main/resources/logback.xml b/persistence-modules/java-calcite/src/main/resources/logback.xml similarity index 89% rename from spring-boot-modules/spring-caching/src/main/resources/logback.xml rename to persistence-modules/java-calcite/src/main/resources/logback.xml index 7d900d8ea8..929cde67ec 100644 --- a/spring-boot-modules/spring-caching/src/main/resources/logback.xml +++ b/persistence-modules/java-calcite/src/main/resources/logback.xml @@ -1,5 +1,5 @@ - + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n @@ -10,4 +10,5 @@ + \ No newline at end of file diff --git a/persistence-modules/liquibase/README.md b/persistence-modules/liquibase/README.md index 0e5bfcb8a6..4b68b8b995 100644 --- a/persistence-modules/liquibase/README.md +++ b/persistence-modules/liquibase/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Introduction to Liquibase Rollback](http://www.baeldung.com/liquibase-rollback) +- [Creating PostgreSQL Schema Before Liquibase Execution](https://www.baeldung.com/java-postgresql-create-schema-before-liquibase) diff --git a/persistence-modules/liquibase/pom.xml b/persistence-modules/liquibase/pom.xml index a6e0ed85e9..5caf7047ac 100644 --- a/persistence-modules/liquibase/pom.xml +++ b/persistence-modules/liquibase/pom.xml @@ -4,13 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 liquibase + com.baeldung liquibase - - - com.baeldung - persistence-modules - 1.0.0-SNAPSHOT - + 0.0.1-SNAPSHOT @@ -18,6 +14,38 @@ mysql-connector-j ${mysql-connector-java.version} + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + org.slf4j + slf4j-log4j12 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + org.liquibase + liquibase-core + ${liquibase.version} + + + org.postgresql + postgresql + ${postgresql.version} + runtime + + + net.lbruun.springboot + preliquibase-spring-boot-starter + ${preliquibase.version} + @@ -32,12 +60,30 @@ liquibase/db-changelog.xml + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.release} + --enable-preview + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + 8.2.0 4.25.0 + 17 + 17 + 17 + 17 + 3.2.3 + 4.26.0 + 42.7.2 + 1.5.0 \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java new file mode 100644 index 0000000000..f501cbf82a --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.liquibase; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LiquibaseCreateSchemaApplication { + + public static void main(String[] args) { + SpringApplication.run(LiquibaseCreateSchemaApplication.class, args); + } +} diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java new file mode 100644 index 0000000000..cf122070c2 --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java @@ -0,0 +1,31 @@ +package com.baeldung.liquibase.configuration; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class SchemaInitializer implements BeanPostProcessor { + + @Value("${spring.liquibase.default-schema}") + private String schemaName; + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof DataSource) { + DataSource dataSource = (DataSource) bean; + try { + Connection conn = dataSource.getConnection(); + Statement statement = conn.createStatement(); + statement.execute(String.format("CREATE SCHEMA IF NOT EXISTS %s", schemaName)); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return bean; + } +} \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java new file mode 100644 index 0000000000..9beedfb55f --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java @@ -0,0 +1,30 @@ +package com.baeldung.liquibase.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/liquibase/src/main/resources/application.properties b/persistence-modules/liquibase/src/main/resources/application.properties new file mode 100644 index 0000000000..77740c8e2b --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/application.properties @@ -0,0 +1,5 @@ +#spring.datasource.url=jdbc:postgresql://some-postgresql-host/some-postgresql-database +#spring.datasource.username=your-postgresql-username +#spring.datasource.password=your-postgresql-password +#spring.liquibase.change-log=classpath:liquibase/changelog.xml +#spring.liquibase.default-schema=user_management \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml b/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml new file mode 100644 index 0000000000..e33bc1610a --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml @@ -0,0 +1,22 @@ + + + + + + CREATE SCHEMA IF NOT EXISTS user_management; + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml new file mode 100644 index 0000000000..6ae5187a92 --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql b/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql new file mode 100644 index 0000000000..03aad1cbd4 --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql @@ -0,0 +1 @@ +CREATE SCHEMA IF NOT EXISTS user_management; \ No newline at end of file diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 6d60340128..7512e99441 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -82,17 +82,18 @@ spring-data-jpa-annotations spring-data-jpa-annotations-2 spring-data-jpa-crud - spring-data-jpa-crud-2 spring-data-jpa-enterprise spring-data-jpa-enterprise-2 spring-data-jpa-filtering spring-data-jpa-query spring-data-jpa-query-2 spring-data-jpa-query-3 + spring-data-jpa-query-4 spring-data-jpa-repo spring-data-jpa-repo-2 spring-data-jpa-repo-4 spring-data-jdbc + spring-data-jpa-simple spring-data-keyvalue spring-data-mongodb spring-data-mongodb-2 @@ -107,6 +108,7 @@ spring-hibernate-6 spring-jpa spring-jpa-2 + spring-jpa-3 spring-jdbc spring-jdbc-2 diff --git a/persistence-modules/querydsl/README.md b/persistence-modules/querydsl/README.md index 03e113795d..1e1cf0f464 100644 --- a/persistence-modules/querydsl/README.md +++ b/persistence-modules/querydsl/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Intro to Querydsl](https://www.baeldung.com/intro-to-querydsl) - [A Guide to Querydsl with JPA](https://www.baeldung.com/querydsl-with-jpa-tutorial) +- [Querydsl vs. JPA Criteria](https://www.baeldung.com/jpa-criteria-querydsl-differences) diff --git a/persistence-modules/querydsl/pom.xml b/persistence-modules/querydsl/pom.xml index 72cdb3a48a..c40b97d1b9 100644 --- a/persistence-modules/querydsl/pom.xml +++ b/persistence-modules/querydsl/pom.xml @@ -15,6 +15,18 @@ + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-test + test + ${spring-boot.version} + com.querydsl @@ -36,6 +48,16 @@ ${hibernate-core.version} compile + + org.hibernate + hibernate-jpamodelgen + ${hibernate-core.version} + + + org.bsc.maven + maven-processor-plugin + 5.0 + commons-dbcp commons-dbcp @@ -103,24 +125,36 @@ ${maven-compiler-plugin.version} -proc:none + 17 + 17 - - com.mysema.maven - apt-maven-plugin - ${apt-maven-plugin.version} + org.bsc.maven + maven-processor-plugin + 5.0 + process process + generate-sources - target/generated-sources/java - com.querydsl.apt.jpa.JPAAnnotationProcessor + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + org.hibernate + hibernate-jpamodelgen + ${hibernate-core.version} + + @@ -132,6 +166,7 @@ 1.4 1.1.3 6.4.2.Final + 3.2.3 \ No newline at end of file diff --git a/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/GroupUser.java b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/GroupUser.java new file mode 100644 index 0000000000..32f35cbeb7 --- /dev/null +++ b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/GroupUser.java @@ -0,0 +1,59 @@ +package com.baeldung.querydslvsjpacriteria.entities; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; + +@Entity +public class GroupUser { + + @Id + @GeneratedValue + private Long id; + + private String login; + + @ManyToMany(mappedBy = "groupUsers", cascade = CascadeType.PERSIST) + private Set userGroups = new HashSet<>(); + + @OneToMany(cascade = CascadeType.PERSIST, mappedBy = "groupUser") + private Set tasks = new HashSet<>(0); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public Set getUserGroups() { + return userGroups; + } + + public void setUserGroups(Set userGroups) { + this.userGroups = userGroups; + } + + public Set getTasks() { + return tasks; + } + + public void setTasks(Set tasks) { + this.tasks = tasks; + } +} diff --git a/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/Task.java b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/Task.java new file mode 100644 index 0000000000..ddb522711c --- /dev/null +++ b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/Task.java @@ -0,0 +1,43 @@ +package com.baeldung.querydslvsjpacriteria.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; + +@Entity +public class Task { + + @Id + @GeneratedValue + private Long id; + + private String description; + + @ManyToOne + private GroupUser groupUser; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public GroupUser getUser() { + return groupUser; + } + + public void setUser(GroupUser groupUser) { + this.groupUser = groupUser; + } +} diff --git a/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/UserGroup.java b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/UserGroup.java new file mode 100644 index 0000000000..f6a8b52983 --- /dev/null +++ b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/entities/UserGroup.java @@ -0,0 +1,47 @@ +package com.baeldung.querydslvsjpacriteria.entities; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; + +@Entity +public class UserGroup { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToMany(cascade = CascadeType.PERSIST) + private Set groupUsers = new HashSet<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getGroupUsers() { + return groupUsers; + } + + public void setGroupUsers(Set groupUsers) { + this.groupUsers = groupUsers; + } +} diff --git a/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupJpaSpecificationRepository.java b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupJpaSpecificationRepository.java new file mode 100644 index 0000000000..72d14145af --- /dev/null +++ b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupJpaSpecificationRepository.java @@ -0,0 +1,25 @@ +package com.baeldung.querydslvsjpacriteria.repositories; + +import java.util.List; + +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import com.baeldung.querydslvsjpacriteria.entities.UserGroup; +import com.baeldung.querydslvsjpacriteria.entities.UserGroup_; + +public interface UserGroupJpaSpecificationRepository extends JpaRepository, + JpaSpecificationExecutor { + + default List findAllWithNameInAnyList(List names1, List names2) { + return findAll(specNameInAnyList(names1, names2)); + } + + default Specification specNameInAnyList(List names1, List names2) { + return (root, q, cb) -> cb.or( + root.get(UserGroup_.name).in(names1), + root.get(UserGroup_.name).in(names2) + ); + } +} diff --git a/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupQuerydslPredicateRepository.java b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupQuerydslPredicateRepository.java new file mode 100644 index 0000000000..22d36e9cc8 --- /dev/null +++ b/persistence-modules/querydsl/src/main/java/com/baeldung/querydslvsjpacriteria/repositories/UserGroupQuerydslPredicateRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.querydslvsjpacriteria.repositories; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; + +import com.baeldung.querydslvsjpacriteria.entities.QUserGroup; +import com.baeldung.querydslvsjpacriteria.entities.UserGroup; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Predicate; + +public interface UserGroupQuerydslPredicateRepository extends JpaRepository, QuerydslPredicateExecutor { + + default List findAllWithNameInAnyList(List names1, List names2) { + return StreamSupport + .stream(findAll(predicateInAnyList(names1, names2)).spliterator(), false) + .collect(Collectors.toList()); + } + + default Predicate predicateInAnyList(List names1, List names2) { + return new BooleanBuilder().and(QUserGroup.userGroup.name.in(names1)) + .or(QUserGroup.userGroup.name.in(names2)); + } +} diff --git a/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/QuerydslVSJPACriteriaIntegrationTest.java b/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/QuerydslVSJPACriteriaIntegrationTest.java new file mode 100644 index 0000000000..7827430211 --- /dev/null +++ b/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/QuerydslVSJPACriteriaIntegrationTest.java @@ -0,0 +1,270 @@ +package com.baeldung.querydslvsjpacriteria; + +import static com.baeldung.querydslvsjpacriteria.entities.GroupUser_.tasks; +import static com.baeldung.querydslvsjpacriteria.entities.QGroupUser.groupUser; +import static com.baeldung.querydslvsjpacriteria.entities.QTask.task; +import static com.baeldung.querydslvsjpacriteria.entities.QUserGroup.userGroup; +import static com.baeldung.querydslvsjpacriteria.entities.UserGroup_.GROUP_USERS; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.baeldung.querydslvsjpacriteria.entities.GroupUser; +import com.baeldung.querydslvsjpacriteria.entities.Task; +import com.baeldung.querydslvsjpacriteria.entities.UserGroup; +import com.baeldung.querydslvsjpacriteria.entities.UserGroup_; +import com.baeldung.querydslvsjpacriteria.repositories.UserGroupJpaSpecificationRepository; +import com.baeldung.querydslvsjpacriteria.repositories.UserGroupQuerydslPredicateRepository; +import com.querydsl.core.Tuple; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.CriteriaUpdate; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Root; + +@EnableJpaRepositories(basePackages = {"com.baeldung.querydslvsjpacriteria.repositories"}) +@ContextConfiguration("/test-context.xml") +@ExtendWith({SpringExtension.class, TimingExtension.class}) +class QuerydslVSJPACriteriaIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(QuerydslVSJPACriteriaIntegrationTest.class); + + private static EntityManagerFactory emf; + + private EntityManager em; + + private JPAQueryFactory queryFactory; + + @Autowired + private UserGroupJpaSpecificationRepository userGroupJpaSpecificationRepository; + + @Autowired + private UserGroupQuerydslPredicateRepository userQuerydslPredicateRepository; + + @BeforeAll + static void populateDatabase() { + emf = Persistence.createEntityManagerFactory("com.baeldung.querydsl.intro"); + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + + Stream.of("Group 1", "Group 2", "Group 3") + .forEach(g -> { + UserGroup userGroup = new UserGroup(); + userGroup.setName(g); + em.persist(userGroup); + IntStream.range(0, 10) + .forEach(u -> { + GroupUser groupUser = new GroupUser(); + groupUser.setLogin("User" + u); + groupUser.getUserGroups().add(userGroup); + em.persist(groupUser); + userGroup.getGroupUsers().add(groupUser); + IntStream.range(0, 10000) + .forEach(t -> { + Task task = new Task(); + task.setDescription(groupUser.getLogin() + " task #" + t); + task.setUser(groupUser); + em.persist(task); + }); + }); + em.merge(userGroup); + }); + + em.getTransaction().commit(); + em.close(); + } + + @BeforeEach + void setUp() { + em = emf.createEntityManager(); + em.getTransaction().begin(); + queryFactory = new JPAQueryFactory(em); + + createUserGroup("Group 1"); + createUserGroup("Group 4"); + } + + @Test + void givenJpaCriteria_whenGetAllTheUserGroups_thenExpectedNumberOfItemsShouldBePresent() { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cr = cb.createQuery(UserGroup.class); + Root root = cr.from(UserGroup.class); + CriteriaQuery select = cr.select(root); + + TypedQuery query = em.createQuery(select); + List results = query.getResultList(); + assertEquals(3, results.size()); + } + + @Test + void givenQueryDSL_whenGetAllTheUserGroups_thenExpectedNumberOfItemsShouldBePresent() { + List results = queryFactory.selectFrom(userGroup).fetch(); + assertEquals(3, results.size()); + } + + @Test + void givenJpaCriteria_whenGetTheUserGroups_thenExpectedAggregatedDataShouldBePresent() { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cr = cb.createQuery(Object[].class); + Root root = cr.from(UserGroup.class); + + CriteriaQuery select = cr + .multiselect(root.get(UserGroup_.name), cb.countDistinct(root.get(UserGroup_.id))) + .where(cb.or( + root.get(UserGroup_.name).in("Group 1", "Group 2"), + root.get(UserGroup_.name).in("Group 4", "Group 5") + )) + .orderBy(cb.desc(root.get(UserGroup_.name))) + .groupBy(root.get(UserGroup_.name)); + + TypedQuery query = em.createQuery(select); + List results = query.getResultList(); + assertEquals(2, results.size()); + assertEquals("Group 2", results.get(0)[0]); + assertEquals(1L, results.get(0)[1]); + assertEquals("Group 1", results.get(1)[0]); + assertEquals(1L, results.get(1)[1]); + } + + @Test + void givenQueryDSL_whenGetTheUserGroups_thenExpectedAggregatedDataShouldBePresent() { + List results = queryFactory + .select(userGroup.name, userGroup.id.countDistinct()) + .from(userGroup) + .where(userGroup.name.in("Group 1", "Group 2") + .or(userGroup.name.in("Group 4", "Group 5"))) + .orderBy(userGroup.name.desc()) + .groupBy(userGroup.name) + .fetch(); + + assertEquals(2, results.size()); + assertEquals("Group 2", results.get(0).get(userGroup.name)); + assertEquals(1L, results.get(0).get(userGroup.id.countDistinct())); + assertEquals("Group 1", results.get(1).get(userGroup.name)); + assertEquals(1L, results.get(1).get(userGroup.id.countDistinct())); + } + + @Test + void givenJpaCriteria_whenGetTheUserGroupsWithJoins_thenExpectedDataShouldBePresent() { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(UserGroup.class); + + query.from(UserGroup.class) + .join(GROUP_USERS, JoinType.LEFT) + .join(tasks, JoinType.LEFT); + + List result = em.createQuery(query).getResultList(); + assertUserGroups(result); + } + + private void assertUserGroups(List userGroups) { + assertEquals(3, userGroups.size()); + for (UserGroup group : userGroups) { + assertEquals(10, group.getGroupUsers().size()); + for (GroupUser user : group.getGroupUsers()) { + assertEquals(10000, user.getTasks().size()); + } + } + } + + @Test + void givenQueryDSL_whenGetTheUserGroupsWithJoins_thenExpectedDataShouldBePresent() { + List result = queryFactory + .selectFrom(userGroup) + .leftJoin(userGroup.groupUsers, groupUser) + .leftJoin(groupUser.tasks, task) + .fetch(); + + assertUserGroups(result); + } + + @Test + void givenJpaCriteria_whenModifyTheUserGroup_thenNameShouldBeUpdated() { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(UserGroup.class); + Root root = criteriaUpdate.from(UserGroup.class); + criteriaUpdate.set(UserGroup_.name, "Group 1 Updated using Jpa Criteria"); + criteriaUpdate.where(cb.equal(root.get(UserGroup_.name), "Group 1")); + + em.createQuery(criteriaUpdate).executeUpdate(); + UserGroup foundGroup = em.find(UserGroup.class, 1L); + assertEquals("Group 1 Updated using Jpa Criteria", foundGroup.getName()); + renameEntityBack(foundGroup, "Group 1"); + } + + private void renameEntityBack(UserGroup foundGroup, String name) { + foundGroup.setName(name); + em.merge(foundGroup); + } + + @Test + void givenQueryDSL_whenModifyTheUserGroup_thenNameShouldBeUpdated() { + queryFactory.update(userGroup) + .set(userGroup.name, "Group 1 Updated Using QueryDSL") + .where(userGroup.name.eq("Group 1")) + .execute(); + + UserGroup foundGroup = em.find(UserGroup.class, 1L); + assertEquals("Group 1 Updated Using QueryDSL", foundGroup.getName()); + renameEntityBack(foundGroup, "Group 1"); + } + + @Test + void givenJpaSpecificationRepository_whenGetTheUserGroups_thenExpectedDataShouldBePresent() { + List results = userGroupJpaSpecificationRepository.findAllWithNameInAnyList( + List.of("Group 1", "Group 2"), List.of("Group 4", "Group 5")); + + assertEquals(2, results.size()); + assertEquals("Group 1", results.get(0).getName()); + assertEquals("Group 4", results.get(1).getName()); + } + + @Test + void givenQuerydslPredicateRepository_whenGetTheUserGroups_thenExpectedDataShouldBePresent() { + List results = userQuerydslPredicateRepository.findAllWithNameInAnyList( + List.of("Group 1", "Group 2"), List.of("Group 4", "Group 5")); + + assertEquals(2, results.size()); + assertEquals("Group 1", results.get(0).getName()); + assertEquals("Group 4", results.get(1).getName()); + } + + private void createUserGroup(String name) { + UserGroup entity = new UserGroup(); + entity.setName(name); + userGroupJpaSpecificationRepository.save(entity); + } + + @AfterEach + void tearDown() { + em.getTransaction().commit(); + em.close(); + userGroupJpaSpecificationRepository.deleteAll(); + } + + @AfterAll + static void afterClass() { + emf.close(); + } +} diff --git a/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/TimingExtension.java b/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/TimingExtension.java new file mode 100644 index 0000000000..1847dfb5be --- /dev/null +++ b/persistence-modules/querydsl/src/test/java/com/baeldung/querydslvsjpacriteria/TimingExtension.java @@ -0,0 +1,34 @@ +package com.baeldung.querydslvsjpacriteria; + +import java.lang.reflect.Method; + +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback { + private static final Logger logger = LoggerFactory.getLogger(TimingExtension.class); + private static final String START_TIME = "start time"; + + @Override + public void beforeTestExecution(ExtensionContext context) { + getStore(context).put(START_TIME, System.currentTimeMillis()); + } + + @Override + public void afterTestExecution(ExtensionContext context) { + Method testMethod = context.getRequiredTestMethod(); + long startTime = getStore(context).remove(START_TIME, long.class); + long duration = System.currentTimeMillis() - startTime; + + logger.info(String.format("Method [%s] took %s ms.", testMethod.getName(), duration)); + } + + private Store getStore(ExtensionContext context) { + return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod())); + } +} diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index 9b22e6902c..0937e76fa1 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -124,6 +124,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.boot.dependencies} diff --git a/persistence-modules/spring-boot-persistence-3/pom.xml b/persistence-modules/spring-boot-persistence-3/pom.xml index fd4d354c78..2684d4dcd2 100644 --- a/persistence-modules/spring-boot-persistence-3/pom.xml +++ b/persistence-modules/spring-boot-persistence-3/pom.xml @@ -55,6 +55,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.boot.dependencies} diff --git a/persistence-modules/spring-boot-persistence-3/src/main/resources/application.yml b/persistence-modules/spring-boot-persistence-3/src/main/resources/application.yml index bb9e377c34..c805ac963b 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/resources/application.yml +++ b/persistence-modules/spring-boot-persistence-3/src/main/resources/application.yml @@ -1,4 +1,3 @@ - logging.level.org.hibernate: - SQL: DEBUG - type.descriptor.sql.BasicBinder: TRACE \ No newline at end of file + SQL: INFO + type.descriptor.sql.BasicBinder: INFO \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/README.md b/persistence-modules/spring-boot-persistence-4/README.md index 728cb35461..6ddc1621e0 100644 --- a/persistence-modules/spring-boot-persistence-4/README.md +++ b/persistence-modules/spring-boot-persistence-4/README.md @@ -4,3 +4,4 @@ - [N+1 Problem in Hibernate and Spring Data JPA](https://www.baeldung.com/spring-hibernate-n1-problem) - [Get All Results at Once in a Spring Boot Paged Query Method](https://www.baeldung.com/spring-boot-paged-query-all-results) - [Calling Custom Database Functions With JPA and Spring Boot](https://www.baeldung.com/spring-data-jpa-custom-database-functions) +- [Spring Data JPA Repository for Database View](https://www.baeldung.com/spring-data-jpa-repository-view) diff --git a/persistence-modules/spring-boot-persistence-mongodb/README.md b/persistence-modules/spring-boot-persistence-mongodb/README.md index 8e9399f076..5453eb0052 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/README.md +++ b/persistence-modules/spring-boot-persistence-mongodb/README.md @@ -7,4 +7,5 @@ - [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) - [A Guide to @DBRef in MongoDB](https://www.baeldung.com/spring-mongodb-dbref-annotation) - [Import Data to MongoDB From JSON File Using Java](https://www.baeldung.com/java-import-json-mongodb) +- [Spring Data MongoDB – Configure Connection](https://www.baeldung.com/spring-data-mongodb-connection) - More articles: [[next-->]](../spring-boot-persistence-mongodb-2) diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties index 65e65cc96c..2b37be6e57 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties @@ -10,4 +10,5 @@ spring.thymeleaf.cache=false spring.servlet.multipart.max-file-size=256MB spring.servlet.multipart.max-request-size=256MB -spring.servlet.multipart.enabled=true \ No newline at end of file +spring.servlet.multipart.enabled=true +spring.data.mongodb.uri=mongodb://localhost \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbAutoGeneratedFieldIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbAutoGeneratedFieldIntegrationTest.java index e20a229f36..9be3c7e171 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbAutoGeneratedFieldIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbAutoGeneratedFieldIntegrationTest.java @@ -2,30 +2,31 @@ package com.baeldung.mongodb; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.baeldung.mongodb.daos.UserRepository; import com.baeldung.mongodb.models.User; - -@RunWith(SpringRunner.class) -@SpringBootTest +@ExtendWith(SpringExtension.class) @DirtiesContext -public class MongoDbAutoGeneratedFieldIntegrationTest { +@DataMongoTest +class MongoDbAutoGeneratedFieldIntegrationTest { @Autowired UserRepository userRepository; @Test - public void contextLoads() {} + void contextLoads() { + // Verifies the context is loaded correctly + } @Test - public void givenUserObject_whenSave_thenCreateNewUser() { + void givenUserObject_whenSave_thenCreateNewUser() { User user = new User(); user.setFirstName("John"); @@ -33,8 +34,8 @@ public class MongoDbAutoGeneratedFieldIntegrationTest { user.setEmail("john.doe@example.com"); userRepository.save(user); - assertThat(userRepository.findAll().size()).isGreaterThan(0); + assertThat(userRepository.findAll() + .size()).isPositive(); } - } diff --git a/persistence-modules/spring-data-cassandra-2/pom.xml b/persistence-modules/spring-data-cassandra-2/pom.xml index e6f7691c17..91702f49da 100644 --- a/persistence-modules/spring-data-cassandra-2/pom.xml +++ b/persistence-modules/spring-data-cassandra-2/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -63,7 +63,7 @@ com.datastax.oss java-driver-mapper-runtime - 4.15.0 + 4.17.0 org.junit.jupiter @@ -99,10 +99,11 @@ - 3.4.15 - 1.19.0 - 1.1.0 + 4.1.9 + 1.19.5 + 2.1.5 5.9.3 + org.baeldung.springcassandra.SpringCassandraApplication \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-2/src/main/resources/application.properties b/persistence-modules/spring-data-cassandra-2/src/main/resources/application.properties index bea2021070..20a107cb53 100644 --- a/persistence-modules/spring-data-cassandra-2/src/main/resources/application.properties +++ b/persistence-modules/spring-data-cassandra-2/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.data.cassandra.keyspace-name=${CASSANDRA_KEYSPACE_NAME} -spring.data.cassandra.contact-points=${CASSANDRA_CONTACT_POINTS} -spring.data.cassandra.port=${CASSANDRA_PORT} -spring.data.cassandra.local-datacenter=datacenter1 \ No newline at end of file +spring.cassandra.keyspace-name=${CASSANDRA_KEYSPACE_NAME} +spring.cassandra.contact-points=${CASSANDRA_CONTACT_POINTS} +spring.cassandra.port=${CASSANDRA_PORT} +spring.cassandra.local-datacenter=datacenter1 \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/cassandra/inquery/ProductRepositoryNestedLiveTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/cassandra/inquery/ProductRepositoryNestedLiveTest.java index 3d99782afd..531a0241da 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/cassandra/inquery/ProductRepositoryNestedLiveTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/cassandra/inquery/ProductRepositoryNestedLiveTest.java @@ -14,6 +14,8 @@ import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -30,14 +32,14 @@ class ProductRepositoryNestedLiveTest { private static final String KEYSPACE_NAME = "mynamespace"; @Container - private static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2") + private static final CassandraContainer cassandra = new CassandraContainer<>("cassandra:3.11.2") .withExposedPorts(9042); @BeforeAll static void setupCassandraConnectionProperties() { - System.setProperty("spring.data.cassandra.keyspace-name", KEYSPACE_NAME); - System.setProperty("spring.data.cassandra.contact-points", cassandra.getHost()); - System.setProperty("spring.data.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); + System.setProperty("spring.cassandra.keyspace-name", KEYSPACE_NAME); + System.setProperty("spring.cassandra.contact-points", cassandra.getHost()); + System.setProperty("spring.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); createKeyspace(cassandra.getCluster()); } @@ -72,9 +74,9 @@ class ProductRepositoryNestedLiveTest { Product product3 = new Product(productId3, "Banana", "Banana v1", 5.5); Product product4 = new Product(productId3, "Banana v2", "Banana v2", 15.5); - productRepository.saveAll(List.of(product1, product2, product3, product4)); + productRepository.saveAll(Arrays.asList(product1, product2, product3, product4)); - List existingProducts = productRepository.findByProductIds(List.of(productId1, productId2)); + List existingProducts = productRepository.findByProductIds(Arrays.asList(productId1, productId2)); assertEquals(2, existingProducts.size()); assertTrue(existingProducts.contains(product1)); assertTrue(existingProducts.contains(product2)); @@ -89,10 +91,10 @@ class ProductRepositoryNestedLiveTest { Product product3 = new Product(productId2, "Banana", "Banana v1", 5.5); Product product4 = new Product(productId2, "Banana v2", "Banana v2", 15.5); - productRepository.saveAll(List.of(product1, product2, product3, product4)); + productRepository.saveAll(Arrays.asList(product1, product2, product3, product4)); List existingProducts = productRepository.findByProductIdAndNames(productId1, - List.of(product1.getProductName(), product2.getProductName())); + Arrays.asList(product1.getProductName(), product2.getProductName())); assertEquals(2, existingProducts.size()); assertTrue(existingProducts.contains(product1)); assertTrue(existingProducts.contains(product2)); @@ -107,10 +109,11 @@ class ProductRepositoryNestedLiveTest { Product product3 = new Product(productId2, "Banana", "Banana v1", 5.5); Product product4 = new Product(productId2, "Banana v2", "Banana v2", 15.5); - productRepository.saveAll(List.of(product1, product2, product4)); + productRepository.saveAll(Arrays.asList(product1, product2, product4)); List existingProducts = productRepository.findByProductIdAndNames(productId1, - List.of(product3.getProductName())); + Collections.singletonList(product3.getProductName()) + ); assertEquals(0, existingProducts.size()); } } diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java index 50681d36c5..bac503b50f 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java @@ -25,13 +25,13 @@ public class MapperLiveTest { private static final String KEYSPACE_NAME = "baeldung"; @Container - private static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2").withExposedPorts(9042); + private static final CassandraContainer cassandra = new CassandraContainer<>("cassandra:3.11.2").withExposedPorts(9042); @BeforeAll static void setupCassandraConnectionProperties() { - System.setProperty("spring.data.cassandra.keyspace-name", KEYSPACE_NAME); - System.setProperty("spring.data.cassandra.contact-points", cassandra.getHost()); - System.setProperty("spring.data.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); + System.setProperty("spring.cassandra.keyspace-name", KEYSPACE_NAME); + System.setProperty("spring.cassandra.contact-points", cassandra.getHost()); + System.setProperty("spring.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); setupCassandra(new InetSocketAddress(cassandra.getHost(), cassandra.getMappedPort(9042)), cassandra.getLocalDatacenter()); } @@ -92,5 +92,4 @@ public class MapperLiveTest { .all(); Assertions.assertEquals(1, retrievedUsers.size()); } - } \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java index 60f733794d..53787790d8 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java @@ -14,6 +14,7 @@ import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -28,14 +29,14 @@ class CassandraNestedLiveTest { private static final String KEYSPACE_NAME = "test"; @Container - private static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2") + private static final CassandraContainer cassandra = new CassandraContainer<>("cassandra:3.11.2") .withExposedPorts(9042); @BeforeAll static void setupCassandraConnectionProperties() { - System.setProperty("spring.data.cassandra.keyspace-name", KEYSPACE_NAME); - System.setProperty("spring.data.cassandra.contact-points", cassandra.getContainerIpAddress()); - System.setProperty("spring.data.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); + System.setProperty("spring.cassandra.keyspace-name", KEYSPACE_NAME); + System.setProperty("spring.cassandra.contact-points", cassandra.getContainerIpAddress()); + System.setProperty("spring.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); createKeyspace(cassandra.getCluster()); } @@ -70,7 +71,7 @@ class CassandraNestedLiveTest { carRepository.save(newCar); - List savedCars = carRepository.findAllById(List.of(carId)); + List savedCars = carRepository.findAllById(Collections.singletonList(carId)); assertThat(savedCars.get(0)).isEqualTo(newCar); } @@ -82,7 +83,7 @@ class CassandraNestedLiveTest { existingCar.setModel("X-Trail"); carRepository.save(existingCar); - List savedCars = carRepository.findAllById(List.of(carId)); + List savedCars = carRepository.findAllById(Collections.singletonList(carId)); assertThat(savedCars.get(0).getModel()).isEqualTo("X-Trail"); } @@ -93,10 +94,8 @@ class CassandraNestedLiveTest { carRepository.delete(existingCar); - List savedCars = carRepository.findAllById(List.of(carId)); - assertThat(savedCars.isEmpty()).isTrue(); + List savedCars = carRepository.findAllById(Collections.singletonList(carId)); + assertThat(savedCars).isEmpty(); } - } - } diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java index 02dc1f5a87..9d5b31ed03 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java @@ -20,14 +20,14 @@ class CassandraSimpleLiveTest { private static final String KEYSPACE_NAME = "test"; @Container - private static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2") + private static final CassandraContainer cassandra = new CassandraContainer<>("cassandra:3.11.2") .withExposedPorts(9042); @BeforeAll static void setupCassandraConnectionProperties() { - System.setProperty("spring.data.cassandra.keyspace-name", KEYSPACE_NAME); - System.setProperty("spring.data.cassandra.contact-points", cassandra.getContainerIpAddress()); - System.setProperty("spring.data.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); + System.setProperty("spring.cassandra.keyspace-name", KEYSPACE_NAME); + System.setProperty("spring.cassandra.contact-points", cassandra.getContainerIpAddress()); + System.setProperty("spring.cassandra.port", String.valueOf(cassandra.getMappedPort(9042))); createKeyspace(cassandra.getCluster()); } @@ -43,5 +43,4 @@ class CassandraSimpleLiveTest { void givenCassandraContainer_whenSpringContextIsBootstrapped_thenContainerIsRunningWithNoExceptions() { assertThat(cassandra.isRunning()).isTrue(); } - } diff --git a/persistence-modules/spring-data-cassandra-2/src/test/resources/application.properties b/persistence-modules/spring-data-cassandra-2/src/test/resources/application.properties index 58f1fe2ab7..e6bc7b47f4 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/resources/application.properties +++ b/persistence-modules/spring-data-cassandra-2/src/test/resources/application.properties @@ -1,5 +1,5 @@ -spring.data.cassandra.keyspace-name=${CASSANDRA_KEYSPACE_NAME} -spring.data.cassandra.contact-points=${CASSANDRA_CONTACT_POINTS} -spring.data.cassandra.port=${CASSANDRA_PORT} -spring.data.cassandra.local-datacenter=datacenter1 -spring.data.cassandra.schema-action=create_if_not_exists \ No newline at end of file +spring.cassandra.keyspace-name=${CASSANDRA_KEYSPACE_NAME} +spring.cassandra.contact-points=${CASSANDRA_CONTACT_POINTS} +spring.cassandra.port=${CASSANDRA_PORT} +spring.cassandra.local-datacenter=datacenter1 +spring.cassandra.schema-action=create_if_not_exists \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations-2/README.md b/persistence-modules/spring-data-jpa-annotations-2/README.md index f334f60b68..e374e2aad0 100644 --- a/persistence-modules/spring-data-jpa-annotations-2/README.md +++ b/persistence-modules/spring-data-jpa-annotations-2/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [@DataJpaTest and Repository Class in JUnit](https://www.baeldung.com/junit-datajpatest-repository) +- [Query Hints in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-hints) diff --git a/persistence-modules/spring-data-jpa-crud-2/README.md b/persistence-modules/spring-data-jpa-crud-2/README.md deleted file mode 100644 index c912e1d5aa..0000000000 --- a/persistence-modules/spring-data-jpa-crud-2/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Spring Data JPA - CRUD - -This module contains articles about CRUD operations in Spring Data JPA - -### Relevant Articles: -- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) -- More articles: [[<--prev]](/persistence-modules/spring-data-jpa-crud) - -### Eclipse Config -After importing the project into Eclipse, you may see the following error: -"No persistence xml file found in project" - -This can be ignored: -- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" -Or: -- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator diff --git a/persistence-modules/spring-data-jpa-crud-2/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-crud-2/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java deleted file mode 100644 index 86a7671fe4..0000000000 --- a/persistence-modules/spring-data-jpa-crud-2/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.baeldung.schemageneration; - -import com.baeldung.schemageneration.model.Account; -import com.baeldung.schemageneration.model.AccountSetting; -import com.baeldung.schemageneration.repository.AccountRepository; -import com.baeldung.schemageneration.repository.AccountSettingRepository; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = AccountApplication.class) -public class AccountRepositoryIntegrationTest { - - private static final String USER_NAME = "Eduard"; - private static final String USER_EMAIL_ADDRESS = "eduard@gmx.com"; - private static final String ACCOUNT_SETTING_NAME = "Timezone"; - private static final String ACCOUNT_SETTING_VALUE = "UTC+02"; - - @Autowired - private AccountRepository accountRepository; - - @Autowired - private AccountSettingRepository accountSettingRepository; - - @After - public void tearDown() { - accountRepository.deleteAll(); - } - - @Test - public void givenNewAccount_whenSave_thenSuccess() { - Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS); - accountRepository.save(account); - - assertEquals(1, accountRepository.count()); - } - - @Test - public void givenSavedAccount_whenFindByName_thenFound() { - Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS); - accountRepository.save(account); - - Account accountFound = accountRepository.findByName(USER_NAME); - - assertNotNull(accountFound); - assertEquals(USER_NAME, accountFound.getName()); - assertEquals(USER_EMAIL_ADDRESS, accountFound.getEmailAddress()); - } - - @Test - public void givenSavedAccount_whenAccountSettingIsAdded_thenPersisted() { - Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS); - account.addAccountSetting(new AccountSetting(ACCOUNT_SETTING_NAME, ACCOUNT_SETTING_VALUE)); - accountRepository.save(account); - - Account accountFound = accountRepository.findByName(USER_NAME); - assertNotNull(accountFound); - AccountSetting accountSetting = accountSettingRepository.findByAccountId(accountFound.getId()); - - assertNotNull(accountSetting); - assertEquals(ACCOUNT_SETTING_NAME, accountSetting.getSettingName()); - assertEquals(ACCOUNT_SETTING_VALUE, accountSetting.getSettingValue()); - } - -} diff --git a/persistence-modules/spring-data-jpa-enterprise/README.md b/persistence-modules/spring-data-jpa-enterprise/README.md index c48a519a87..de29532dfc 100644 --- a/persistence-modules/spring-data-jpa-enterprise/README.md +++ b/persistence-modules/spring-data-jpa-enterprise/README.md @@ -8,9 +8,7 @@ This module contains articles about Spring Data JPA used in enterprise applicati - [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) - [A Guide to Spring’s Open Session in View](https://www.baeldung.com/spring-open-session-in-view) - [Partial Data Update With Spring Data](https://www.baeldung.com/spring-data-partial-update) -- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) - [Spring JPA – Multiple Databases](https://www.baeldung.com/spring-data-jpa-multiple-databases) -- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-jpa-filtering/README.md b/persistence-modules/spring-data-jpa-filtering/README.md index fe2f181154..b29c0b9e7b 100644 --- a/persistence-modules/spring-data-jpa-filtering/README.md +++ b/persistence-modules/spring-data-jpa-filtering/README.md @@ -6,7 +6,6 @@ This module contains articles about filtering data using Spring Data JPA - [An Advanced Tagging Implementation with JPA](https://www.baeldung.com/jpa-tagging-advanced) - [A Simple Tagging Implementation with JPA](https://www.baeldung.com/jpa-tagging) - [Spring Data JPA and Null Parameters](https://www.baeldung.com/spring-data-jpa-null-parameters) -- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-jpa-query-2/README.md b/persistence-modules/spring-data-jpa-query-2/README.md index e091bc1d99..db1d0cd4c7 100644 --- a/persistence-modules/spring-data-jpa-query-2/README.md +++ b/persistence-modules/spring-data-jpa-query-2/README.md @@ -4,7 +4,6 @@ This module contains articles about querying data using Spring Data JPA . ### Relevant Articles: -- [Spring Data JPA @Query](https://www.baeldung.com/spring-data-jpa-query) - [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries) - [Hibernate Pagination](https://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](https://www.baeldung.com/hibernate-sort) diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/QueryApplication.java similarity index 88% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/QueryApplication.java index d7a1950305..a7d029b54d 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/QueryApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.derivedquery; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -10,4 +10,4 @@ public class QueryApplication { SpringApplication.run(QueryApplication.class, args); } -} +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java new file mode 100644 index 0000000000..127b56ef0f --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java @@ -0,0 +1,57 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import org.springframework.data.jpa.domain.Specification; + +@Entity +public class Book { + + @Id + @GeneratedValue + private Long id; + private String title; + private String author; + + public Book(String title, String author) { + this.title = title; + this.author = author; + } + + public Book() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + static Specification hasAuthor(String author) { + return (book, cq, cb) -> cb.equal(book.get("author"), author); + } + + static Specification titleContains(String title) { + return (book, cq, cb) -> cb.like(book.get("title"), "%" + title + "%"); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java new file mode 100644 index 0000000000..61c47a1d85 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.criteriaquery; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +interface BookRepository extends JpaRepository, BookRepositoryCustom, JpaSpecificationExecutor { +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java new file mode 100644 index 0000000000..9863cb72a3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java @@ -0,0 +1,9 @@ +package com.baeldung.criteriaquery; + +import java.util.List; + +interface BookRepositoryCustom { + + List findBooksByAuthorNameAndTitle(String authorName, String title); + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java new file mode 100644 index 0000000000..c227bf6e96 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java @@ -0,0 +1,39 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class BookRepositoryImpl implements BookRepositoryCustom { + + @Autowired + private EntityManager em; + + @Override + public List findBooksByAuthorNameAndTitle(String authorName, String title) { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Book.class); + + Root book = cq.from(Book.class); + List predicates = new ArrayList<>(); + + if (authorName != null) { + predicates.add(cb.equal(book.get("author"), authorName)); + } + if (title != null) { + predicates.add(cb.like(book.get("title"), "%" + title + "%")); + } + cq.where(predicates.toArray(new Predicate[0])); + + return em.createQuery(cq).getResultList(); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java new file mode 100644 index 0000000000..5f28b01997 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +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.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static com.baeldung.criteriaquery.Book.hasAuthor; +import static com.baeldung.criteriaquery.Book.titleContains; +import static org.junit.Assert.assertEquals; +import static org.springframework.data.jpa.domain.Specification.where; + +@DataJpaTest(showSql = false) +@RunWith(SpringRunner.class) +public class CriteriaQueryIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private BookRepository repository; + + @Before + public void before() { + entityManager.persist(new Book("title1", "author1")); + entityManager.persist(new Book("title2", "author2")); + } + + @Test + public void givenAuthorAndTextInTitle_whenFindWithSpecification_ThenFound() { + List books = repository.findAll(where(hasAuthor("author1")).and(titleContains("1"))); + assertEquals(1, books.size()); + assertEquals("author1", books.get(0).getAuthor()); + assertEquals("title1", books.get(0).getTitle()); + } + + @Test + public void givenAuthorAndTextInTitle_whenFindWithCriteriaQuery_ThenFound() { + List books = repository.findBooksByAuthorNameAndTitle("author2", "2"); + assertEquals(1, books.size()); + assertEquals("author2", books.get(0).getAuthor()); + assertEquals("title2", books.get(0).getTitle()); + } + +} diff --git a/persistence-modules/spring-data-jpa-crud-2/pom.xml b/persistence-modules/spring-data-jpa-query-4/pom.xml similarity index 63% rename from persistence-modules/spring-data-jpa-crud-2/pom.xml rename to persistence-modules/spring-data-jpa-query-4/pom.xml index ff90d0ed8b..3b843aed20 100644 --- a/persistence-modules/spring-data-jpa-crud-2/pom.xml +++ b/persistence-modules/spring-data-jpa-query-4/pom.xml @@ -3,8 +3,8 @@ 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 - spring-data-jpa-crud-2 - spring-data-jpa-crud-2 + spring-data-jpa-query-4 + spring-data-jpa-query-4 com.baeldung @@ -14,19 +14,32 @@ + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot - spring-boot-starter-web + spring-boot-starter-test + test com.h2database h2 - runtime + + + org.postgresql + postgresql + ${postgresql.version} + + 42.7.1 + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/Product.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/Product.java new file mode 100644 index 0000000000..ffe81fa13b --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/Product.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.data.jpa.queryjsonb; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Product { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + @Column(columnDefinition = "jsonb") + private String attributes; + + public Product() { + } + + public Product(String name, String attributes) { + this.name = name; + this.attributes = attributes; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAttributes() { + return attributes; + } + + public void setAttributes(String attributes) { + this.attributes = attributes; + } + +} diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductApplication.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductApplication.java new file mode 100644 index 0000000000..dc237ddf58 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.data.jpa.queryjsonb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ProductApplication { + + public static void main(String[] args) { + SpringApplication.run(ProductApplication.class); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepository.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepository.java new file mode 100644 index 0000000000..8667afb3f4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.data.jpa.queryjsonb; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface ProductRepository extends JpaRepository, JpaSpecificationExecutor { + @Query(value = "SELECT * FROM product WHERE attributes ->> ?1 = ?2", nativeQuery = true) + List findByAttribute(String key, String value); + + @Query(value = "SELECT * FROM product WHERE attributes -> ?1 ->> ?2 = ?3", nativeQuery = true) + List findByNestedAttribute(String key1, String key2, String value); + + @Query(value = "SELECT * FROM product WHERE jsonb_extract_path_text(attributes, ?1) = ?2", nativeQuery = true) + List findByJsonPath(String path, String value); + + @Query(value = "SELECT * FROM product WHERE jsonb_extract_path_text(attributes, ?1, ?2) = ?3", nativeQuery = true) + List findByNestedJsonPath(String key1, String key2, String value); + + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductSpecification.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductSpecification.java new file mode 100644 index 0000000000..65c9507cf0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/queryjsonb/ProductSpecification.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.data.jpa.queryjsonb; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.springframework.data.jpa.domain.Specification; +public class ProductSpecification implements Specification { + + private final String key; + private final String value; + + public ProductSpecification(String key, String value) { + this.key = key; this.value = value; + } + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return cb.equal(cb.function("jsonb_extract_path_text", String.class, root.get("attributes"), cb.literal(key)), value); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-query-4/src/main/resources/application.properties new file mode 100644 index 0000000000..de0685b9bd --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/resources/application.properties @@ -0,0 +1,10 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/postgres +spring.datasource.username=postgres +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true + +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..2385590d7f --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.spring.data.jpa.queryjsonb; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; + +import javax.transaction.Transactional; + +import org.junit.Before; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageImpl; +import org.springframework.test.annotation.Commit; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Propagation; +import com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@ActiveProfiles("test") +@Sql(scripts = "/testdata.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) +public class ProductRepositoryIntegrationTest { + + @Autowired + private ProductRepository productRepository; + + @Test + void whenFindByAttribute_thenReturnTheObject() { + List redProducts = productRepository.findByAttribute("color", "red"); + + assertEquals(1, redProducts.size()); + assertEquals("Laptop", redProducts.get(0).getName()); + } + + @Test + void whenFindByNestedAttribute_thenReturnTheObject() { + List electronicProducts = productRepository.findByNestedAttribute("details", "category", "electronics"); + + assertEquals(1, electronicProducts.size()); + assertEquals("Headphones", electronicProducts.get(0) + .getName()); + } + + @Test + void whenFindByJsonPath_thenReturnTheObject() { + List redProducts = productRepository.findByJsonPath("color", "red"); + assertEquals(1, redProducts.size()); + assertEquals("Laptop", redProducts.get(0) + .getName()); + } + + @Test + void givenNestedJsonAttribute_whenFindByJsonPath_thenReturnTheObject() { + List electronicProducts = productRepository.findByNestedJsonPath("details", "category", "electronics"); + assertEquals(1, electronicProducts.size()); + assertEquals("Headphones", electronicProducts.get(0) + .getName()); + } + + @Test + void whenUsingJPASpecification_thenReturnTheObject() { + ProductSpecification spec = new ProductSpecification("color", "red"); + Page redProducts = productRepository.findAll(spec, Pageable.unpaged()); + + assertEquals(1, redProducts.getContent() + .size()); + assertEquals("Laptop", redProducts.getContent() + .get(0) + .getName()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/resources/application-test.properties b/persistence-modules/spring-data-jpa-query-4/src/test/resources/application-test.properties new file mode 100644 index 0000000000..af1e12cb9c --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/test/resources/application-test.properties @@ -0,0 +1,10 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/postgres +spring.datasource.username=postgres +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true + +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/resources/testdata.sql b/persistence-modules/spring-data-jpa-query-4/src/test/resources/testdata.sql new file mode 100644 index 0000000000..71e9a3123d --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/test/resources/testdata.sql @@ -0,0 +1,13 @@ +DELETE FROM product; + +INSERT INTO product (name, attributes) +VALUES ('Laptop', '{"color": "red", "size": "15 inch"}'); + +INSERT INTO product (name, attributes) +VALUES ('Phone', '{"color": "blue", "size": "6 inch"}'); + +INSERT INTO product (name, attributes) +VALUES ('Headphones', '{"brand": "Sony", "details": {"category": "electronics", "model": "WH-1000XM4"}}'); + +INSERT INTO product (name, attributes) +VALUES ('Laptop', '{"brand": "Dell", "details": {"category": "computers", "model": "XPS 13"}}'); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/README.md b/persistence-modules/spring-data-jpa-query/README.md index 27e7087592..db923dd56a 100644 --- a/persistence-modules/spring-data-jpa-query/README.md +++ b/persistence-modules/spring-data-jpa-query/README.md @@ -4,7 +4,6 @@ This module contains articles about querying data using Spring Data JPA ### Relevant Articles: - [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query) -- [Customizing the Result of JPA Queries with Aggregation Functions](https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions) - [Limiting Query Results With JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results) - [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting) - [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) diff --git a/persistence-modules/spring-data-jpa-query/pom.xml b/persistence-modules/spring-data-jpa-query/pom.xml index da63854859..08d5528023 100644 --- a/persistence-modules/spring-data-jpa-query/pom.xml +++ b/persistence-modules/spring-data-jpa-query/pom.xml @@ -34,11 +34,13 @@ org.springframework spring-oxm + ${spring-oxm.version} 1.4.1 + 6.1.4 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md index 8c588405f7..d377104c02 100644 --- a/persistence-modules/spring-data-jpa-repo-2/README.md +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -7,4 +7,6 @@ - [Difference Between JPA and Spring Data JPA](https://www.baeldung.com/spring-data-jpa-vs-jpa) - [Differences Between Spring Data JPA findFirst() and findTop()](https://www.baeldung.com/spring-data-jpa-findfirst-vs-findtop) - [Difference Between findBy and findAllBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-find-by-vs-find-all-by) +- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) + - More articles: [[<-- prev]](../spring-data-jpa-repo) diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java similarity index 83% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java index 5f05764e21..0100beec55 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.storedprocedure; +package com.baeldung.spring.data.persistence.storedprocedure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java similarity index 86% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java index 6aef600d01..6a12e4e93b 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java @@ -1,14 +1,13 @@ -package com.baeldung.storedprocedure.controller; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.controller; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; +import com.baeldung.spring.data.persistence.storedprocedure.service.CarService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.storedprocedure.entity.Car; -import com.baeldung.storedprocedure.service.CarService; +import java.util.List; @RestController public class CarController { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java similarity index 93% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java index 0a61a16e24..53f1d8557e 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java @@ -1,4 +1,4 @@ -package com.baeldung.storedprocedure.entity; +package com.baeldung.spring.data.persistence.storedprocedure.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java similarity index 87% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java index 3d9428628e..9366a86445 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java @@ -1,14 +1,13 @@ -package com.baeldung.storedprocedure.repository; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.repository; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.query.Procedure; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import com.baeldung.storedprocedure.entity.Car; +import java.util.List; @Repository public interface CarRepository extends JpaRepository { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java similarity index 81% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java index 104f46e324..ff2a20601e 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java @@ -1,12 +1,11 @@ -package com.baeldung.storedprocedure.service; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.service; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; +import com.baeldung.spring.data.persistence.storedprocedure.repository.CarRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.baeldung.storedprocedure.entity.Car; -import com.baeldung.storedprocedure.repository.CarRepository; +import java.util.List; @Service public class CarService { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/car-mysql.sql similarity index 100% rename from persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql rename to persistence-modules/spring-data-jpa-repo-2/src/main/resources/car-mysql.sql diff --git a/persistence-modules/spring-data-jpa-repo-3/README.md b/persistence-modules/spring-data-jpa-repo-3/README.md index 03b0e7f76b..dbd7b67e2c 100644 --- a/persistence-modules/spring-data-jpa-repo-3/README.md +++ b/persistence-modules/spring-data-jpa-repo-3/README.md @@ -3,10 +3,10 @@ This module contains articles about Spring Data JPA. ### Relevant Articles: -- [New CRUD Repository Interfaces in Spring Data 3](https://www.baeldung.com/spring-data-3-crud-repository-interfaces) - [How to Persist a List of String in JPA?](https://www.baeldung.com/java-jpa-persist-string-list) - [Hibernate Natural IDs in Spring Boot](https://www.baeldung.com/spring-boot-hibernate-natural-ids) - [Correct Use of flush() in JPA](https://www.baeldung.com/spring-jpa-flush) - [Difference Between findBy and findOneBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-findby-vs-findoneby) - [How to Get Last Record in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-last-record) +- [Refresh and Fetch an Entity After Save in JPA](https://www.baeldung.com/spring-data-jpa-refresh-fetch-entity-after-save) - More articles: [[<-- prev]](../spring-data-jpa-repo-2) diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/Order.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/Order.java new file mode 100644 index 0000000000..f25513dc12 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/Order.java @@ -0,0 +1,79 @@ +package com.baeldung.fetchandrefresh; + +import java.time.LocalDate; +import java.util.List; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Version; + +@Entity +public class Order { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @OneToMany(mappedBy = "order", fetch = FetchType.EAGER) + private List orderItems; + + private LocalDate orderDate; + + private String name; + + private String customerName; + + @Version + private Long version; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getOrderItems() { + return orderItems; + } + + public void setOrderItems(List orderItems) { + this.orderItems = orderItems; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderItem.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderItem.java new file mode 100644 index 0000000000..c3c59987a8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderItem.java @@ -0,0 +1,63 @@ +package com.baeldung.fetchandrefresh; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; + +@Entity +public class OrderItem { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + private int quantity; + private double price; + + @JoinColumn(name = "order_id") + private Order order; + + // Getters and setters + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public Order getOrder() { + return order; + } + + public void setOrder(Order order) { + this.order = order; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderRepository.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderRepository.java new file mode 100644 index 0000000000..9de20d9184 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.fetchandrefresh; + +import java.time.LocalDate; +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface OrderRepository extends JpaRepository { + + @Query("SELECT o FROM Order o WHERE o.customerName = :customerName AND o.orderDate BETWEEN :startDate AND :endDate") + List findOrdersByCustomerAndDateRange(@Param("customerName") String customerName, @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate); +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderService.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderService.java new file mode 100644 index 0000000000..1f1665fa79 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/fetchandrefresh/OrderService.java @@ -0,0 +1,62 @@ +package com.baeldung.fetchandrefresh; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import org.aspectj.weaver.ast.Or; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityNotFoundException; +import jakarta.persistence.OptimisticLockException; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + +@Service +public class OrderService { + + @Autowired + private EntityManager entityManager; + + @Autowired + private OrderRepository orderRepository; + + public List findOrdersByCustomerAndDateRangeUsingCriteriaAPI(String customerName, LocalDate startDate, LocalDate endDate) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Order.class); + Root root = criteriaQuery.from(Order.class); + + Predicate customerPredicate = criteriaBuilder.equal(root.get("customerName"), customerName); + Predicate dateRangePredicate = criteriaBuilder.between(root.get("orderDate"), startDate, endDate); + + criteriaQuery.where(customerPredicate, dateRangePredicate); + + return entityManager.createQuery(criteriaQuery) + .getResultList(); + } + + public void updateOrderName(long orderId, String newName) { + Order order = orderRepository.findById(orderId) + .map(existingOrder -> { + existingOrder.setName(newName); + return existingOrder; + }) + .orElseGet(() -> { + return null; + }); + + if (order != null) { + try { + orderRepository.save(order); + } catch (OptimisticLockException e) { + // Refresh the entity and potentially retry the update + entityManager.refresh(order); + // Consider adding logic to handle retries or notify the user about the conflict + } + } + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java new file mode 100644 index 0000000000..840d26edf7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.data.jpa.joinquery; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableAutoConfiguration +public class AppConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) + .build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { + LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); + emf.setDataSource(dataSource); + emf.setPackagesToScan("com.baeldung.spring.data.jpa.joinquery.entities" + , "com.baeldung.spring.data.jpa.joinquery.DTO" + , "com.baeldung.spring.data.jpa.joinquery.repositories"); + emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + emf.setJpaProperties(getHibernateProperties()); + return emf; + } + + @Bean + public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory.getObject()); + } + + private Properties getHibernateProperties() { + Properties properties = new Properties(); + properties.setProperty("hibernate.hbm2ddl.auto", "create"); + properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + return properties; + } +} + + + + diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java new file mode 100644 index 0000000000..9464c25ce8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java @@ -0,0 +1,119 @@ +package com.baeldung.spring.data.jpa.joinquery.DTO; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import org.springframework.context.annotation.Bean; + +import java.time.LocalDate; + +class DTO { + private Long customer_id; + private Long order_id; + private Long product_id; + + public DTO(Long customer_id, Long order_id, Long product_id) { + this.customer_id = customer_id; + this.order_id = order_id; + this.product_id = product_id; + } +} + +@Entity +@IdClass(DTO.class) +public class ResultDTO { + @Id + private Long customer_id; + + @Id + private Long order_id; + + @Id + private Long product_id; + + public void setCustomer_id(Long customer_id) { + this.customer_id = customer_id; + } + + public Long getProduct_id() { + return product_id; + } + + public void setProduct_id(Long product_id) { + this.product_id = product_id; + } + + public ResultDTO(Long customer_id, Long order_id, Long product_id, String customerName, String customerEmail, LocalDate orderDate, String productName, Double productPrice) { + this.customer_id = customer_id; + this.order_id = order_id; + this.product_id = product_id; + this.customerName = customerName; + this.customerEmail = customerEmail; + this.orderDate = orderDate; + this.productName = productName; + this.productPrice = productPrice; + } + + private String customerName; + private String customerEmail; + private LocalDate orderDate; + private String productName; + private Double productPrice; + + public Long getCustomer_id() { + return customer_id; + } + + public void setCustoemr_id(Long custoemr_id) { + this.customer_id = custoemr_id; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getCustomerEmail() { + return customerEmail; + } + + public void setCustomerEmail(String customerEmail) { + this.customerEmail = customerEmail; + } + + public Long getOrder_id() { + return order_id; + } + + public void setOrder_id(Long order_id) { + this.order_id = order_id; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Double getProductPrice() { + return productPrice; + } + + public void setProductPrice(Double productPrice) { + this.productPrice = productPrice; + } + +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO_wo_Ids.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO_wo_Ids.java new file mode 100644 index 0000000000..540ad9fc91 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO_wo_Ids.java @@ -0,0 +1,66 @@ +package com.baeldung.spring.data.jpa.joinquery.DTO; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; + +import java.time.LocalDate; + +//@Entity +//@IdClass(DTO.class) +public class ResultDTO_wo_Ids { + public ResultDTO_wo_Ids(String customerName, String customerEmail, LocalDate orderDate, String productName, Double productPrice) { + this.customerName = customerName; + this.customerEmail = customerEmail; + this.orderDate = orderDate; + this.productName = productName; + this.productPrice = productPrice; + } + + private String customerName; + private String customerEmail; + private LocalDate orderDate; + private String productName; + private Double productPrice; + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getCustomerEmail() { + return customerEmail; + } + + public void setCustomerEmail(String customerEmail) { + this.customerEmail = customerEmail; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Double getProductPrice() { + return productPrice; + } + + public void setProductPrice(Double productPrice) { + this.productPrice = productPrice; + } + +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java new file mode 100644 index 0000000000..8da7aa21a2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java @@ -0,0 +1,104 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Set; + +@Entity +public class Customer { + public Customer(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToMany(mappedBy = "customer" + , cascade = CascadeType.ALL) + private Set customerOrders; + + public Customer(Long id, Set customerOrders, String email, LocalDate dob, String name) { + this.id = id; + this.customerOrders = customerOrders; + this.email = email; + this.dob = dob; + this.name = name; + } + + public void setId(Long id) { + this.id = id; + } + + public void setCustomerOrders(Set customerOrders) { + this.customerOrders = customerOrders; + } + + @Override + public String toString() { + return "Patient{" + + "id=" + id + + ", orders=" + customerOrders + + ", email='" + email + '\'' + + ", dob=" + dob + + ", name='" + name + '\'' + + '}'; + } + + public Set getOrders() { + return customerOrders; + } + + public void setOrders(Set orders) { + this.customerOrders = orders; + } + + @Column + private String email; + + @Column(name = "dob", columnDefinition = "DATE") + private LocalDate dob; + + @Column + private String name; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Customer patient = (Customer) o; + return Objects.equals(id, patient.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public Long getId() { + return id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public LocalDate getDob() { + return dob; + } + + public void setDob(LocalDate dob) { + this.dob = dob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java new file mode 100644 index 0000000000..d147543e2f --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java @@ -0,0 +1,88 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Set; + +@Entity +public class CustomerOrder { + public CustomerOrder(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public void setId(Long id) { + this.id = id; + } + + public Set getProducts() { + return products; + } + + public void setProducts(Set products) { + this.products = products; + } + + @OneToMany(mappedBy = "customerOrder" + , cascade = CascadeType.ALL) + private Set products; + + @Column + private LocalDate orderDate; + + public CustomerOrder(Long id, Set products, LocalDate orderDate, Customer customer) { + this.id = id; + this.products = products; + this.orderDate = orderDate; + this.customer = customer; + } + + @Override + public String toString() { + return "Consult{" + + "id=" + id + + ", products=" + products + + ", orderDate=" + orderDate + + ", customer=" + customer + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomerOrder co = (CustomerOrder) o; + return Objects.equals(id, co.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="customer_id", nullable = false) + private Customer customer; + + public Long getId() { + return id; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java new file mode 100644 index 0000000000..ea18e6225e --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java @@ -0,0 +1,84 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.util.Objects; + +@Entity +public class Product { + public Product(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public Product(Long id, String productName, Double price, CustomerOrder customerOrder) { + this.id = id; + this.productName = productName; + this.price = price; + this.customerOrder = customerOrder; + } + + @Column + private String productName; + + @Column + private Double price; + + @Override + public String toString() { + return "Dispense{" + + "id=" + id + + ", productName='" + productName + '\'' + + ", price=" + price + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Product dispense = (Product) o; + return Objects.equals(id, dispense.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public CustomerOrder getCustomerOrder() { + return customerOrder; + } + + public void setCustomerOrder(CustomerOrder co) { + this.customerOrder = co; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="customerorder_id", nullable = false) + private CustomerOrder customerOrder; +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java new file mode 100644 index 0000000000..ba7ece74b8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.data.jpa.joinquery.repositories; + +import com.baeldung.spring.data.jpa.joinquery.entities.Customer; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CustomerRepository extends CrudRepository { +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java new file mode 100644 index 0000000000..056c91f973 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java @@ -0,0 +1,34 @@ +package com.baeldung.spring.data.jpa.joinquery.repositories; + +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO; +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Map; + +@Repository +public interface JoinRepository extends CrudRepository { + @Query(value = "SELECT new com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO(c.id, o.id, p.id, c.name, c.email, o.orderDate, p.productName, p.price) " + + " from Customer c, CustomerOrder o ,Product p " + + " where c.id=o.customer.id " + + " and o.id=p.customerOrder.id " + + " and c.id=?1 ") + List findResultDTOByCustomer(Long id); + + @Query(value = "SELECT new com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids(c.name, c.email, o.orderDate, p.productName, p.price) " + + " from Customer c, CustomerOrder o ,Product p " + + " where c.id=o.customer.id " + + " and o.id=p.customerOrder.id " + + " and c.id=?1 ") + List findResultDTOByCustomerWithoutIds(Long id); + + @Query(value = "SELECT c.*, o.*, p.* " + + " from Customer c, CustomerOrder o ,Product p " + + " where c.id=o.customer_id " + + " and o.id=p.customerOrder_id " + + " and c.id=?1 " + , nativeQuery = true) + List> findByCustomer(Long id); +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryUnitTest.java new file mode 100644 index 0000000000..dd91399128 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryUnitTest.java @@ -0,0 +1,106 @@ +package com.baeldung.spring.data.jpa.joinquery; + +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids; +import com.baeldung.spring.data.jpa.joinquery.entities.Customer; +import com.baeldung.spring.data.jpa.joinquery.entities.CustomerOrder; +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO; +import com.baeldung.spring.data.jpa.joinquery.entities.Product; +import com.baeldung.spring.data.jpa.joinquery.repositories.CustomerRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.PersistenceUnit; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.baeldung.spring.data.jpa.joinquery.repositories.JoinRepository; +import java.time.LocalDate; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { AppConfig.class }) +class JoinRepositoryUnitTest { + + @Autowired + JoinRepository joinRepository; + + @Autowired + CustomerRepository customerRepository; + + @PersistenceUnit + EntityManagerFactory entityManagerFactory; + + EntityManager entityManager; + + @BeforeEach + void setUp() { + customerRepository.deleteAll(); + entityManager = entityManagerFactory.createEntityManager(); + Customer c = new Customer(1L, null, "email1@email.com", LocalDate.now(), "Customer"); + CustomerOrder o1 = new CustomerOrder(1L, null, LocalDate.now(), c); + CustomerOrder o2 = new CustomerOrder(2L, null, LocalDate.of(2024,1,1), c); + + Product p1 = new Product(1L,"Product1", 25.20, o1); + Product p2 = new Product(2L, "Product2", 26.20, o1); + Product p3 = new Product(3L, "Product3", 27.20, o2); + + Set cos01 = new HashSet<>(); + cos01.add(o1); + cos01.add(o2); + Set productsO1 = new HashSet<>(); + productsO1.add(p1); + productsO1.add(p2); + Set productsO2 = new HashSet<>(); + productsO1.add(p3); + + c.setCustomerOrders(cos01); + o1.setProducts(productsO1); + o2.setProducts(productsO2); + + EntityTransaction et = getTransaction(); + entityManager.persist(c); + entityManager.flush(); + et.commit(); + } + + @AfterEach + void tearDown() { + } + + @Test + void whenFindResultDTOByCustomer_thenReturnResultDTO() { + List resultDTO = joinRepository.findResultDTOByCustomer(1L); + assertInstanceOf(ResultDTO.class, resultDTO.get(0)); + } + + @Test + void whenFindByCustomerNativeQuery_thenReturnMapsForObjects() { + List> res = joinRepository.findByCustomer(1L); + //the map objects in the res List has 9 String keys aka 9 columns corresponding to the columns of customer, customerOrder, product + res.forEach(map -> { + assertEquals(9, map.keySet().size()); + }); + } + + @Test + void whenFindResultDTOByCustomerWithoutIds_thenReturnResultDTO() { + List resultDTO = joinRepository.findResultDTOByCustomerWithoutIds(1L); + assertInstanceOf(ResultDTO_wo_Ids.class, resultDTO.get(0)); + } + + private EntityTransaction getTransaction() { + EntityTransaction transaction = entityManager.getTransaction(); + transaction.begin(); + return transaction; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/LibraryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/LibraryIntegrationTest.java index 7bd1b90407..5b1b51adc5 100644 --- a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/LibraryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/LibraryIntegrationTest.java @@ -10,14 +10,14 @@ import org.springframework.boot.test.context.SpringBootTest; import java.util.Arrays; @SpringBootTest -public class LibraryIntegrationTest { +class LibraryIntegrationTest { @Autowired private LibraryRepository libraryRepository; @Test @Transactional - public void givenLibrary_whenGetAddressesAndGetBooks_thenGetListOfItems(){ + void givenLibrary_whenGetAddressesAndGetBooks_thenGetListOfItems(){ Library library = new Library(); library.setAddresses(Arrays.asList("Address 1", "Address 2")); library.setBooks(Arrays.asList("Book 1", "Book 2")); diff --git a/persistence-modules/spring-data-jpa-repo/README.md b/persistence-modules/spring-data-jpa-repo/README.md index ef3442929e..ffbd57d7f6 100644 --- a/persistence-modules/spring-data-jpa-repo/README.md +++ b/persistence-modules/spring-data-jpa-repo/README.md @@ -2,15 +2,12 @@ This module contains articles about repositories in Spring Data JPA -### Relevant Articles: -- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) +### Relevant Articles: - [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries) -- [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries) - [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) - [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories) - [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories) - [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators) -- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) - [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries) - More articles: [[--> next]](../spring-data-jpa-repo-2) diff --git a/persistence-modules/spring-data-jpa-repo/pom.xml b/persistence-modules/spring-data-jpa-repo/pom.xml index 1eed56266a..2ead30e7da 100644 --- a/persistence-modules/spring-data-jpa-repo/pom.xml +++ b/persistence-modules/spring-data-jpa-repo/pom.xml @@ -41,6 +41,7 @@ org.springframework spring-oxm + ${spring-oxm.version} com.google.guava @@ -74,4 +75,8 @@ + + 6.1.4 + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java deleted file mode 100644 index cf479780a1..0000000000 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.baeldung.derivedquery.repository; - -import com.baeldung.derivedquery.QueryApplication; -import com.baeldung.derivedquery.entity.User; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = QueryApplication.class) -public class UserRepositoryIntegrationTest { - - private static final String USER_NAME_ADAM = "Adam"; - private static final String USER_NAME_EVE = "Eve"; - private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now(); - - @Autowired - private UserRepository userRepository; - - @Before - public void setUp() { - - User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true); - User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false); - User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true); - User user4 = new User(null, 30, BIRTHDATE, false); - - userRepository.saveAll(Arrays.asList(user1, user2, user3, user4)); - } - - @After - public void tearDown() { - - userRepository.deleteAll(); - } - - @Test - public void whenFindByName_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByName(USER_NAME_ADAM).size()); - } - - @Test - public void whenFindByNameIsNull_thenReturnsCorrectResult() { - - assertEquals(1, userRepository.findByNameIsNull().size()); - } - - @Test - public void whenFindByNameNot_thenReturnsCorrectResult() { - - assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM).get(0).getName()); - } - - @Test - public void whenFindByNameStartingWith_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByNameStartingWith("A").size()); - } - - @Test - public void whenFindByNameEndingWith_thenReturnsCorrectResult() { - - assertEquals(1, userRepository.findByNameEndingWith("e").size()); - } - - @Test - public void whenByNameContaining_thenReturnsCorrectResult() { - - assertEquals(1, userRepository.findByNameContaining("v").size()); - } - - - @Test - public void whenByNameLike_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByNameEndingWith("m").size()); - } - - @Test - public void whenByAgeLessThan_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByAgeLessThan(25).size()); - } - - - @Test - public void whenByAgeLessThanEqual_thenReturnsCorrectResult() { - - assertEquals(3, userRepository.findByAgeLessThanEqual(25).size()); - } - - @Test - public void whenByAgeGreaterThan_thenReturnsCorrectResult() { - - assertEquals(1, userRepository.findByAgeGreaterThan(25).size()); - } - - @Test - public void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByAgeGreaterThanEqual(25).size()); - } - - @Test - public void whenByAgeBetween_thenReturnsCorrectResult() { - - assertEquals(4, userRepository.findByAgeBetween(20, 30).size()); - } - - @Test - public void whenByBirthDateAfter_thenReturnsCorrectResult() { - - final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); - assertEquals(4, userRepository.findByBirthDateAfter(yesterday).size()); - } - - @Test - public void whenByBirthDateBefore_thenReturnsCorrectResult() { - - final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); - assertEquals(0, userRepository.findByBirthDateBefore(yesterday).size()); - } - - @Test - public void whenByActiveTrue_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByActiveTrue().size()); - } - - @Test - public void whenByActiveFalse_thenReturnsCorrectResult() { - - assertEquals(2, userRepository.findByActiveFalse().size()); - } - - - @Test - public void whenByAgeIn_thenReturnsCorrectResult() { - - final List ages = Arrays.asList(20, 25); - assertEquals(3, userRepository.findByAgeIn(ages).size()); - } - - @Test - public void whenByNameOrAge() { - - assertEquals(3, userRepository.findByNameOrAge(USER_NAME_ADAM, 20).size()); - } - - @Test - public void whenByNameOrAgeAndActive() { - - assertEquals(2, userRepository.findByNameOrAgeAndActive(USER_NAME_ADAM, 20, false).size()); - } - - @Test - public void whenByNameOrderByName() { - - assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM).size()); - } -} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/README.md b/persistence-modules/spring-data-jpa-simple/README.md new file mode 100644 index 0000000000..4d96acb0f4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/README.md @@ -0,0 +1,20 @@ +### Spring Data JPA Articles that are also part of the e-book + +This module contains articles about Spring Data JPA that are also part of an Ebook. + + +### NOTE: + +Since this is a module tied to an e-book, it should **not** be moved or used to store the code for any further article. + +### Relevant Articles +- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) +- [Customizing the Result of JPA Queries with Aggregation Functions](https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions) +- [CrudRepository, JpaRepository, and PagingAndSortingRepository in Spring Data](https://www.baeldung.com/spring-data-repositories) +- [New CRUD Repository Interfaces in Spring Data 3](https://www.baeldung.com/spring-data-3-crud-repository-interfaces) +- [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries) +- [Spring Data JPA @Query](https://www.baeldung.com/spring-data-jpa-query) +- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections) +- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) +- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) +- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/pom.xml b/persistence-modules/spring-data-jpa-simple/pom.xml new file mode 100644 index 0000000000..dc59b1fd22 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + spring-data-jpa-simple + spring-data-jpa-simple + + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + com.mysql + mysql-connector-j + + + org.postgresql + postgresql + + + com.h2database + h2 + runtime + + + org.springframework + spring-oxm + + + com.google.guava + guava + ${guava.version} + + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind.version} + + + org.hibernate.orm + hibernate-ant + ${hibernate.version} + + + + + 6.4.2.Final + 4.0.0 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + + repackage + + + true + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/AggregationApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/AggregationApplication.java new file mode 100644 index 0000000000..eebafa387c --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/AggregationApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.jpa.aggregation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource("classpath:aggregation.properties") +@Configuration +public class AggregationApplication { + + public static void main(String[] args) { + SpringApplication.run(AggregationApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Comment.java similarity index 97% rename from persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Comment.java index 8b4872e05e..8d871fd3fa 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Comment.java @@ -1,9 +1,10 @@ -package com.baeldung.aggregation.model; +package com.baeldung.jpa.aggregation.model; + +import java.util.Objects; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; -import java.util.Objects; @Entity public class Comment { diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Post.java similarity index 96% rename from persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Post.java index 25f48c386e..b0c4fc1523 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/Post.java @@ -1,13 +1,15 @@ -package com.baeldung.aggregation.model; +package com.baeldung.jpa.aggregation.model; + +import java.util.List; +import java.util.Objects; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import java.util.List; -import java.util.Objects; @Entity public class Post { + @Id private Integer id; private String title; diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/CommentCount.java similarity index 89% rename from persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/CommentCount.java index 510b52a47c..f70157c514 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/CommentCount.java @@ -1,4 +1,4 @@ -package com.baeldung.aggregation.model.custom; +package com.baeldung.jpa.aggregation.model.custom; public class CommentCount { private Integer year; diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/ICommentCount.java similarity index 65% rename from persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/ICommentCount.java index acb25cfd49..645cda8a35 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/model/custom/ICommentCount.java @@ -1,4 +1,4 @@ -package com.baeldung.aggregation.model.custom; +package com.baeldung.jpa.aggregation.model.custom; public interface ICommentCount { diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/repository/CommentRepository.java similarity index 70% rename from persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/repository/CommentRepository.java index 5309581638..f0312e0784 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/aggregation/repository/CommentRepository.java @@ -1,13 +1,14 @@ -package com.baeldung.aggregation.repository; +package com.baeldung.jpa.aggregation.repository; + +import java.util.List; -import com.baeldung.aggregation.model.Comment; -import com.baeldung.aggregation.model.custom.CommentCount; -import com.baeldung.aggregation.model.custom.ICommentCount; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import java.util.List; +import com.baeldung.jpa.aggregation.model.Comment; +import com.baeldung.jpa.aggregation.model.custom.CommentCount; +import com.baeldung.jpa.aggregation.model.custom.ICommentCount; @Repository public interface CommentRepository extends JpaRepository { @@ -15,7 +16,7 @@ public interface CommentRepository extends JpaRepository { @Query("SELECT c.year, COUNT(c.year) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") List countTotalCommentsByYear(); - @Query("SELECT new com.baeldung.aggregation.model.custom.CommentCount(c.year, COUNT(c.year)) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") + @Query("SELECT new com.baeldung.jpa.aggregation.model.custom.CommentCount(c.year, COUNT(c.year)) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") List countTotalCommentsByYearClass(); @Query("SELECT c.year AS yearComment, COUNT(c.year) AS totalComment FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java new file mode 100644 index 0000000000..af7fa9a9f1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.jpa.modifying; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication +@EnableJpaRepositories("com.baeldung.jpa.modifying.repository") +@EntityScan("com.baeldung.jpa.modifying.model") +public class ModifyingApplication { + + public static void main(String[] args) { + SpringApplication.run(ModifyingApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java new file mode 100644 index 0000000000..b7e6051810 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java @@ -0,0 +1,84 @@ +package com.baeldung.jpa.modifying.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table +public class Possession { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + public Possession() { + super(); + } + + public Possession(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Possession other = (Possession) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "Possession [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java new file mode 100644 index 0000000000..846d2532e5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java @@ -0,0 +1,136 @@ +package com.baeldung.jpa.modifying.model; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + private String name; + private LocalDate creationDate; + private LocalDate lastLoginDate; + private boolean active; + private int age; + @Column(unique = true, nullable = false) + private String email; + private Integer status; + @OneToMany + List possessionList; + + public User() { + super(); + } + + public User(String name, LocalDate creationDate,String email, Integer status) { + this.name = name; + this.creationDate = creationDate; + this.email = email; + this.status = status; + this.active = true; + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + + @Override + public String toString() { + return "User [name=" + name + ", id=" + id + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return id == user.id && + age == user.age && + Objects.equals(name, user.name) && + Objects.equals(creationDate, user.creationDate) && + Objects.equals(email, user.email) && + Objects.equals(status, user.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, creationDate, age, email, status); + } + + public LocalDate getLastLoginDate() { + return lastLoginDate; + } + + public void setLastLoginDate(LocalDate lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java new file mode 100644 index 0000000000..3c3f9dc1b3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java @@ -0,0 +1,37 @@ +package com.baeldung.jpa.modifying.repository; + +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Stream; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.baeldung.jpa.modifying.model.User; + +public interface UserRepository extends JpaRepository { + + Stream findAllByName(String name); + + void deleteAllByCreationDateAfter(LocalDate date); + + @Query("select u from User u where u.email like '%@gmail.com'") + List findUsersWithGmailAddress(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("update User u set u.active = false where u.lastLoginDate < :date") + void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("delete User u where u.active = false") + int deleteDeactivatedUsers(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "alter table USERS add column deleted int not null default 0", nativeQuery = true) + void addDeletedColumn(); + + @Query("delete User u where u.active = false") + int deleteDeactivatedUsersWithNoModifyingAnnotation(); +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java new file mode 100644 index 0000000000..6049bce07c --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.jpa.paginationsorting; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "com.baeldung.jpa.paginationsorting") +public class PaginationSortingApplication { + + public static void main(String[] args) { + SpringApplication.run(PaginationSortingApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java new file mode 100644 index 0000000000..77ca127d33 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java @@ -0,0 +1,63 @@ +package com.baeldung.jpa.paginationsorting.config; + +import java.util.HashMap; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; + +import com.google.common.base.Preconditions; + +@Configuration +@PropertySource({ "classpath:pagination-sorting-db.properties" }) +@EnableJpaRepositories(basePackages = "com.baeldung.jpa.paginationsorting", entityManagerFactoryRef = "productEntityManager", transactionManagerRef = "productTransactionManager") +public class PersistenceProductConfiguration { + private final Environment env; + + public PersistenceProductConfiguration(Environment env) { + this.env = env; + } + + @Bean + public LocalContainerEntityManagerFactoryBean productEntityManager() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(productDataSource()); + em.setPackagesToScan("com.baeldung.jpa.paginationsorting"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + final HashMap properties = new HashMap(); + properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); + em.setJpaPropertyMap(properties); + + return em; + } + + @Bean + public DataSource productDataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("product.jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager productTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(productEntityManager().getObject()); + return transactionManager; + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java new file mode 100644 index 0000000000..188ebcaf56 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java @@ -0,0 +1,67 @@ +package com.baeldung.jpa.paginationsorting.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(schema = "products") +public class Product { + + @Id + private int id; + + private String name; + + private double price; + + public Product() { + super(); + } + + private Product(int id, String name, double price) { + super(); + this.id = id; + this.name = name; + this.price = price; + } + + public static Product from(int id, String name, double price) { + return new Product(id, name, price); + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(final double price) { + this.price = price; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Product [name=") + .append(name) + .append(", id=") + .append(id) + .append("]"); + return builder.toString(); + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java new file mode 100644 index 0000000000..8c89d88ac8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.jpa.paginationsorting.repository; + +import java.util.List; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.PagingAndSortingRepository; + +import com.baeldung.jpa.paginationsorting.model.Product; + +public interface ProductRepository extends PagingAndSortingRepository, CrudRepository { + + List findAllByPrice(double price, Pageable pageable); + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/ProjectionApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/ProjectionApplication.java new file mode 100644 index 0000000000..469eeaff24 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/ProjectionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.jpa.projection; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ProjectionApplication { + + public static void main(String[] args) { + SpringApplication.run(ProjectionApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Address.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Address.java similarity index 85% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Address.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Address.java index 0c5a3eac60..aa86e056bb 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Address.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Address.java @@ -1,8 +1,8 @@ -package com.baeldung.projection.model; +package com.baeldung.jpa.projection.model; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.OneToOne; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; @Entity public class Address { diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Person.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Person.java similarity index 83% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Person.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Person.java index d18bd1c72d..daec08e703 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/model/Person.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/model/Person.java @@ -1,8 +1,8 @@ -package com.baeldung.projection.model; +package com.baeldung.jpa.projection.model; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.OneToOne; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; @Entity public class Person { diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/AddressRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/AddressRepository.java similarity index 57% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/AddressRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/AddressRepository.java index c1053f4867..1e247f69d8 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/AddressRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/AddressRepository.java @@ -1,11 +1,12 @@ -package com.baeldung.projection.repository; - -import com.baeldung.projection.view.AddressView; -import com.baeldung.projection.model.Address; -import org.springframework.data.repository.Repository; +package com.baeldung.jpa.projection.repository; import java.util.List; +import org.springframework.data.repository.Repository; + +import com.baeldung.jpa.projection.model.Address; +import com.baeldung.jpa.projection.view.AddressView; + public interface AddressRepository extends Repository { List getAddressByState(String state); } diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/PersonRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/PersonRepository.java similarity index 58% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/PersonRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/PersonRepository.java index 64bc7471e6..cd76c97836 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/repository/PersonRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/repository/PersonRepository.java @@ -1,10 +1,11 @@ -package com.baeldung.projection.repository; +package com.baeldung.jpa.projection.repository; -import com.baeldung.projection.model.Person; -import com.baeldung.projection.view.PersonDto; -import com.baeldung.projection.view.PersonView; import org.springframework.data.repository.Repository; +import com.baeldung.jpa.projection.model.Person; +import com.baeldung.jpa.projection.view.PersonDto; +import com.baeldung.jpa.projection.view.PersonView; + public interface PersonRepository extends Repository { PersonView findByLastName(String lastName); diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/AddressView.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/AddressView.java similarity index 67% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/AddressView.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/AddressView.java index 7a24a1e9b9..7ac593b059 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/AddressView.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/AddressView.java @@ -1,4 +1,4 @@ -package com.baeldung.projection.view; +package com.baeldung.jpa.projection.view; public interface AddressView { String getZipCode(); diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonDto.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonDto.java similarity index 95% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonDto.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonDto.java index 1fd924450b..9146e3008c 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonDto.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonDto.java @@ -1,4 +1,4 @@ -package com.baeldung.projection.view; +package com.baeldung.jpa.projection.view; import java.util.Objects; diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonView.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonView.java similarity index 84% rename from persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonView.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonView.java index 36777ec26f..0772832223 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/main/java/com/baeldung/projection/view/PersonView.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/projection/view/PersonView.java @@ -1,4 +1,4 @@ -package com.baeldung.projection.view; +package com.baeldung.jpa.projection.view; import org.springframework.beans.factory.annotation.Value; diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/QueryApplication.java similarity index 69% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/QueryApplication.java index 48c29eda23..fc00c7b4ac 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/QueryApplication.java @@ -1,9 +1,11 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication +//@ComponentScan("com.baeldung.jpa.query") +//@EnableJpaRepositories("com.baeldung.jpa.query") public class QueryApplication { public static void main(String[] args) { diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java similarity index 88% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java index 648b06cf5f..941d045f15 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java @@ -1,10 +1,15 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query.model; -import jakarta.persistence.*; import java.time.LocalDate; -import java.util.List; import java.util.Objects; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + @Entity @Table(name = "users") public class User { @@ -101,9 +106,7 @@ public class User { @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [name=").append(name).append(", id=").append(id).append("]"); - return builder.toString(); + return "User [name=" + name + ", id=" + id + "]"; } @Override diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java similarity index 95% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java index 6547e0ef66..45739aadd4 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java @@ -1,4 +1,7 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query.repository; + +import java.util.Collection; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -7,10 +10,11 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; -import java.util.Collection; -import java.util.List; +import com.baeldung.jpa.query.model.User; +@Repository public interface UserRepository extends JpaRepository, UserRepositoryCustom { @Query("SELECT u FROM User u WHERE u.status = 1") Collection findAllActiveUsers(); diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java similarity index 76% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustom.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java index a3e53528f7..e9f906fedf 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustom.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java @@ -1,14 +1,16 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query.repository; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.function.Predicate; +import com.baeldung.jpa.query.model.User; + public interface UserRepositoryCustom { List findUserByEmails(Set emails); - + List findAllUsersByPredicates(Collection> predicates); } diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java similarity index 82% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java index 54cea74e04..f1c85e95e2 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java @@ -1,8 +1,5 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query.repository; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.persistence.criteria.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -10,6 +7,16 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.baeldung.jpa.query.model.User; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + public class UserRepositoryCustomImpl implements UserRepositoryCustom { @PersistenceContext private EntityManager entityManager; @@ -34,7 +41,7 @@ public class UserRepositoryCustomImpl implements UserRepositoryCustom { return entityManager.createQuery(query) .getResultList(); } - + @Override public List findAllUsersByPredicates(Collection> predicates) { List allUsers = entityManager.createQuery("select u from User u", User.class).getResultList(); diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/AccountApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java similarity index 64% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/AccountApplication.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java index 547992a6c1..367e39507e 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/AccountApplication.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java @@ -1,9 +1,11 @@ -package com.baeldung.schemageneration; +package com.baeldung.jpa.schemageneration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; @SpringBootApplication +@PropertySource("classpath:schema-generation.properties") public class AccountApplication { public static void main(String[] args) { diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/HibernateUtil.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java similarity index 86% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/HibernateUtil.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java index 7d69d65705..910dad26a3 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/HibernateUtil.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java @@ -1,7 +1,9 @@ -package com.baeldung.schemageneration; +package com.baeldung.jpa.schemageneration; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; -import com.baeldung.schemageneration.model.Account; -import com.baeldung.schemageneration.model.AccountSetting; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; @@ -10,9 +12,8 @@ import org.hibernate.cfg.Environment; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.tool.schema.TargetType; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; +import com.baeldung.jpa.schemageneration.model.Account; +import com.baeldung.jpa.schemageneration.model.AccountSetting; public class HibernateUtil { @@ -21,7 +22,7 @@ public class HibernateUtil { * Creation commands are exported into the create.sql file. */ public static void generateSchema() { - Map settings = new HashMap<>(); + Map settings = new HashMap<>(); settings.put(Environment.URL, "jdbc:h2:mem:schema"); StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(settings).build(); diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/Account.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java similarity index 81% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/Account.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java index 785e275e26..e09605c552 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/Account.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java @@ -1,15 +1,16 @@ -package com.baeldung.schemageneration.model; +package com.baeldung.jpa.schemageneration.model; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.Table; import java.util.ArrayList; import java.util.List; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + @Entity @Table(name = "accounts") public class Account { diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java similarity index 79% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java index 61e43894a8..a36a72f73d 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java @@ -1,12 +1,12 @@ -package com.baeldung.schemageneration.model; +package com.baeldung.jpa.schemageneration.model; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; @Entity @Table(name = "account_settings") diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java similarity index 61% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java index dc57ffe6d3..929f3c6980 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java @@ -1,8 +1,9 @@ -package com.baeldung.schemageneration.repository; +package com.baeldung.jpa.schemageneration.repository; -import com.baeldung.schemageneration.model.Account; import org.springframework.data.repository.CrudRepository; +import com.baeldung.jpa.schemageneration.model.Account; + public interface AccountRepository extends CrudRepository { Account findByName(String name); } diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java similarity index 63% rename from persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java index c2b8ff7398..f886bda704 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java @@ -1,8 +1,10 @@ -package com.baeldung.schemageneration.repository; +package com.baeldung.jpa.schemageneration.repository; -import com.baeldung.schemageneration.model.AccountSetting; import org.springframework.data.repository.CrudRepository; +import com.baeldung.jpa.schemageneration.model.AccountSetting; + public interface AccountSettingRepository extends CrudRepository { + AccountSetting findByAccountId(Long accountId); } diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java new file mode 100644 index 0000000000..39efef714d --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.jpa.simple; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication +@EnableJpaRepositories("com.baeldung.jpa.simple.repository") +public class JpaApplication { + + public static void main(String[] args) { + SpringApplication.run(JpaApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java new file mode 100644 index 0000000000..36a1fa9389 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java @@ -0,0 +1,75 @@ +package com.baeldung.jpa.simple.config; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@PropertySource("classpath:persistence.properties") +@EnableTransactionManagement +//@ImportResource("classpath*:*springDataConfig.xml") +public class PersistenceConfig { + + @Autowired + private Environment env; + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan("com.baeldung.jpa.simple.entity"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + return hibernateProperties; + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Book.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Book.java new file mode 100644 index 0000000000..0e01e983b5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Book.java @@ -0,0 +1,57 @@ +package com.baeldung.jpa.simple.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Book { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String title; + private String author; + private String isbn; + + public Book() { + } + + public Book(String title, String author, String isbn) { + this.title = title; + this.author = author; + this.isbn = isbn; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Foo.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Foo.java new file mode 100644 index 0000000000..bf82ab61f7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/Foo.java @@ -0,0 +1,77 @@ +package com.baeldung.jpa.simple.entity; + +import java.io.Serializable; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Foo implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/User.java similarity index 96% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/User.java index b5b5eb40b0..07759af0fb 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/entity/User.java @@ -1,4 +1,4 @@ -package com.baeldung.derivedquery.entity; +package com.baeldung.jpa.simple.entity; import java.time.ZonedDateTime; diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java similarity index 67% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java index aec8347850..e1540c64bf 100644 --- a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java @@ -1,10 +1,11 @@ -package com.baeldung.spring.data.jpa.listrepositories.repository; +package com.baeldung.jpa.simple.repository; + +import java.util.List; -import com.baeldung.spring.data.jpa.listrepositories.entity.Book; import org.springframework.data.repository.ListCrudRepository; import org.springframework.stereotype.Repository; -import java.util.List; +import com.baeldung.jpa.simple.entity.Book; @Repository public interface BookListRepository extends ListCrudRepository { diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java similarity index 78% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java index 1b37b0d1ef..cb519ed5ea 100644 --- a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java @@ -1,12 +1,13 @@ -package com.baeldung.spring.data.jpa.listrepositories.repository; +package com.baeldung.jpa.simple.repository; + +import java.util.List; -import com.baeldung.spring.data.jpa.listrepositories.entity.Book; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.ListCrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; -import java.util.List; +import com.baeldung.jpa.simple.entity.Book; @Repository public interface BookPagingAndSortingRepository extends PagingAndSortingRepository, ListCrudRepository { diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java new file mode 100644 index 0000000000..d6d1d46122 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java @@ -0,0 +1,15 @@ +package com.baeldung.jpa.simple.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.baeldung.jpa.simple.entity.Foo; + +public interface IFooDAO extends JpaRepository { + + Foo findByName(String name); + + @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") + Foo retrieveByName(@Param("name") String name); +} diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java similarity index 87% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java index 7d4a208d26..cc13aac5db 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java @@ -1,15 +1,14 @@ -package com.baeldung.derivedquery.repository; - -import com.baeldung.derivedquery.entity.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; +package com.baeldung.jpa.simple.repository; import java.time.ZonedDateTime; import java.util.Collection; import java.util.List; -public interface UserRepository extends JpaRepository { +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.jpa.simple.entity.User; + +public interface UserRepository extends JpaRepository, UserRepositoryCustom { List findByName(String name); @@ -58,9 +57,9 @@ public interface UserRepository extends JpaRepository { List findByNameOrderByName(String name); List findByNameOrderByNameDesc(String name); - + List findByNameIsNotNull(); - + List findByNameOrderByNameAsc(String name); } diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java new file mode 100644 index 0000000000..8584f3f3bb --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java @@ -0,0 +1,16 @@ +package com.baeldung.jpa.simple.repository; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import com.baeldung.jpa.simple.entity.User; + +public interface UserRepositoryCustom { + + List findUserByEmails(Set emails); + + List findAllUsersByPredicates(Collection> predicates); + +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java new file mode 100644 index 0000000000..b60ca65d0a --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java @@ -0,0 +1,57 @@ +package com.baeldung.jpa.simple.repository; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.baeldung.jpa.simple.entity.User; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + +public class UserRepositoryCustomImpl implements UserRepositoryCustom { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findUserByEmails(Set emails) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(User.class); + Root user = query.from(User.class); + + Path emailPath = user.get("email"); + + List predicates = new ArrayList<>(); + for (String email : emails) { + + predicates.add(cb.like(emailPath, email)); + + } + query.select(user) + .where(cb.or(predicates.toArray(new Predicate[predicates.size()]))); + + return entityManager.createQuery(query) + .getResultList(); + } + + @Override + public List findAllUsersByPredicates(Collection> predicates) { + List allUsers = entityManager.createQuery("select u from User u", User.class) + .getResultList(); + Stream allUsersStream = allUsers.stream(); + for (java.util.function.Predicate predicate : predicates) { + allUsersStream = allUsersStream.filter(predicate); + } + + return allUsersStream.collect(Collectors.toList()); + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java new file mode 100644 index 0000000000..f02c1eebad --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java @@ -0,0 +1,19 @@ +package com.baeldung.jpa.simple.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.jpa.simple.entity.Foo; +import com.baeldung.jpa.simple.repository.IFooDAO; + +@Service +public class FooService implements IFooService { + + @Autowired + private IFooDAO dao; + + @Override + public Foo create(Foo foo) { + return dao.save(foo); + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java new file mode 100644 index 0000000000..4fc56bde87 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java @@ -0,0 +1,7 @@ +package com.baeldung.jpa.simple.service; + +import com.baeldung.jpa.simple.entity.Foo; + +public interface IFooService { + Foo create(Foo foo); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/aggregation.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/aggregation.properties new file mode 100644 index 0000000000..bb3bb903a4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/aggregation.properties @@ -0,0 +1,3 @@ +spring.jpa.show-sql=false +spring.jpa.defer-datasource-initialization=true +spring.jpa.properties.hibernate.globally_quoted_identifiers=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/application.properties new file mode 100644 index 0000000000..1a370121c5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.jpa.show-sql=false +spring.jpa.defer-datasource-initialization=true +#MySql +#spring.datasource.url=jdbc:mysql://localhost:3306/baeldung +#spring.datasource.username=baeldung +#spring.datasource.password=baeldung \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/insert_users.sql b/persistence-modules/spring-data-jpa-simple/src/main/resources/insert_users.sql new file mode 100644 index 0000000000..e0aca9ac41 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/insert_users.sql @@ -0,0 +1,8 @@ +insert into Users(name, creation_date, last_login_date, active, age, email, status) +values('John', PARSEDATETIME('01/01/2018', 'dd/MM/yyyy'), PARSEDATETIME('01/01/2020', 'dd/MM/yyyy'), 1, 23, 'john@email.com', 1); + +insert into Users(name, creation_date, last_login_date, active, age, email, status) +values('Bob', PARSEDATETIME('02/02/2019', 'dd/MM/yyyy'), PARSEDATETIME('02/02/2020', 'dd/MM/yyyy'), 1, 56, 'bob@email.com', 1); + +insert into Users(name, creation_date, last_login_date, active, age, email, status) +values('Cindy', PARSEDATETIME('02/02/2019', 'dd/MM/yyyy'), PARSEDATETIME('02/02/2020', 'dd/MM/yyyy'), 1, 18, 'cindy@email.com', 0); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/pagination-sorting-db.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/pagination-sorting-db.properties new file mode 100644 index 0000000000..82dd3b0025 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/pagination-sorting-db.properties @@ -0,0 +1,6 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +product.jdbc.url=jdbc:h2:mem:spring_jpa_product;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PRODUCTS +jdbc.user=sa +jdbc.pass=sa +hibernate.hbm2ddl.auto=create-drop diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/persistence.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/persistence.properties new file mode 100644 index 0000000000..05cb7a13b9 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/persistence.properties @@ -0,0 +1,9 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +jdbc.pass=sa + +# hibernate.X +hibernate.hbm2ddl.auto=create-drop +hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/persistence-modules/spring-data-jpa-crud-2/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/schema-generation.properties similarity index 98% rename from persistence-modules/spring-data-jpa-crud-2/src/main/resources/application.properties rename to persistence-modules/spring-data-jpa-simple/src/main/resources/schema-generation.properties index ead0df89a3..76ffe6932b 100644 --- a/persistence-modules/spring-data-jpa-crud-2/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/schema-generation.properties @@ -1 +1 @@ -spring.jpa.properties.hibernate.globally_quoted_identifiers=true +spring.jpa.properties.hibernate.globally_quoted_identifiers=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/main/resources/springDataConfig.xml b/persistence-modules/spring-data-jpa-simple/src/main/resources/springDataConfig.xml new file mode 100644 index 0000000000..12de60da73 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/resources/springDataConfig.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/aggregation/SpringDataAggregateIntegrationTest.java similarity index 88% rename from persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/aggregation/SpringDataAggregateIntegrationTest.java index a73ad949db..0fbe94532a 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/aggregation/SpringDataAggregateIntegrationTest.java @@ -1,23 +1,28 @@ -package com.baeldung.aggregation; - -import com.baeldung.aggregation.model.custom.CommentCount; -import com.baeldung.aggregation.model.custom.ICommentCount; -import com.baeldung.aggregation.repository.CommentRepository; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.List; +package com.baeldung.jpa.aggregation; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigurationPackage; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.jpa.aggregation.model.custom.CommentCount; +import com.baeldung.jpa.aggregation.model.custom.ICommentCount; +import com.baeldung.jpa.aggregation.repository.CommentRepository; + @RunWith(SpringRunner.class) @DataJpaTest(showSql = false) @Sql(scripts = "/test-aggregation-data.sql") +@AutoConfigurationPackage(basePackages = "com.baeldung.jpa.aggregation") +@ContextConfiguration(classes = AggregationApplication.class) public class SpringDataAggregateIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java new file mode 100644 index 0000000000..872f1be985 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java @@ -0,0 +1,212 @@ +package com.baeldung.jpa.modifying; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.domain.Sort; +import org.springframework.data.mapping.PropertyReferenceException; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.jpa.modifying.repository.UserRepository; +import com.baeldung.jpa.modifying.model.User; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.Query; + +@SpringBootTest(classes= ModifyingApplication.class) +class UserRepositoryCommonIntegrationTest { + + final String USER_EMAIL = "email@example.com"; + final String USER_EMAIL2 = "email2@example.com"; + final String USER_EMAIL3 = "email3@example.com"; + final String USER_EMAIL4 = "email4@example.com"; + final Integer INACTIVE_STATUS = 0; + final Integer ACTIVE_STATUS = 1; + final String USER_NAME_ADAM = "Adam"; + final String USER_NAME_PETER = "Peter"; + + @Autowired + protected UserRepository userRepository; + @Autowired + private EntityManager entityManager; + + @Test + @Transactional + void givenUsersWithSameNameInDB_WhenFindAllByName_ThenReturnStreamOfUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + User user4 = new User(); + user4.setName("SAMPLE"); + user4.setEmail(USER_EMAIL4); + userRepository.save(user4); + + try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { + assertThat(foundUsersStream.count()).isEqualTo(3l); + } + } + + @Test + void givenUsersInDB_WhenFindAllWithSortByName_ThenReturnUsersSorted() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + + List usersSortByName = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); + + assertThat(usersSortByName.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + + userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); + + assertThrows(PropertyReferenceException.class, () -> userRepository.findAll(Sort.by("LENGTH(name)"))); + } + + @Test + @Transactional + void givenTwoUsers_whenFindByNameUsr01_ThenUserUsr01() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr01")) { + assertTrue(users.allMatch(usr -> usr.equals(usr01))); + } + } + + @Test + @Transactional + void givenTwoUsers_whenFindByNameUsr00_ThenNoUsers() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr00")) { + assertEquals(0, users.count()); + } + } + + @Test + void givenTwoUsers_whenFindUsersWithGmailAddress_ThenUserUsr02() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@gmail.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + List users = userRepository.findUsersWithGmailAddress(); + assertEquals(1, users.size()); + assertEquals(usr02, users.get(0)); + } + + @Test + @Transactional + void givenTwoUsers_whenDeleteAllByCreationDateAfter_ThenOneUserRemains() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deleteAllByCreationDateAfter(LocalDate.of(2018, 5, 1)); + + List users = userRepository.findAll(); + + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + @Transactional + void givenTwoUsers_whenDeleteDeactivatedUsers_ThenUserUsr02Deleted() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 0); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + int deletedUsersCount = userRepository.deleteDeactivatedUsers(); + + List users = userRepository.findAll(); + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + assertEquals(1, deletedUsersCount); + } + + @Test + @Transactional + void givenTwoUsers_whenDeleteDeactivatedUsersWithNoModifyingAnnotation_ThenException() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 0); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + assertThatThrownBy(() -> userRepository.deleteDeactivatedUsersWithNoModifyingAnnotation()) + .isInstanceOf(InvalidDataAccessApiUsageException.class); + } + + @Test + @Transactional + void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.addDeletedColumn(); + + Query nativeQuery = entityManager.createNativeQuery("select deleted from USERS where NAME = 'usr01'"); + assertEquals(0, nativeQuery.getResultList().get(0)); + } + + @AfterEach + void cleanUp() { + userRepository.deleteAll(); + } +} diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java similarity index 77% rename from persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java index 831790af95..9cf65fa949 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java @@ -1,41 +1,38 @@ -package com.baeldung.multipledb; +package com.baeldung.jpa.paginationsorting; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; -import com.baeldung.multipledb.dao.product.ProductRepository; -import com.baeldung.multipledb.model.product.Product; +import com.baeldung.jpa.paginationsorting.model.Product; +import com.baeldung.jpa.paginationsorting.repository.ProductRepository; -@RunWith(SpringRunner.class) -@SpringBootTest(classes=MultipleDbApplication.class) +@SpringBootTest(classes = PaginationSortingApplication.class) @EnableTransactionManagement -public class ProductRepositoryIntegrationTest { +class ProductRepositoryIntegrationTest { @Autowired private ProductRepository productRepository; - @Before + @BeforeEach @Transactional("productTransactionManager") - public void setUp() { + void setUp() { productRepository.save(Product.from(1001, "Book", 21)); productRepository.save(Product.from(1002, "Coffee", 10)); productRepository.save(Product.from(1003, "Jeans", 30)); @@ -44,7 +41,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenRequestingFirstPageOfSizeTwo_ThenReturnFirstPage() { + void whenRequestingFirstPageOfSizeTwo_ThenReturnFirstPage() { Pageable pageRequest = PageRequest.of(0, 2); Page result = productRepository.findAll(pageRequest); @@ -57,7 +54,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenRequestingSecondPageOfSizeTwo_ThenReturnSecondPage() { + void whenRequestingSecondPageOfSizeTwo_ThenReturnSecondPage() { Pageable pageRequest = PageRequest.of(1, 2); Page result = productRepository.findAll(pageRequest); @@ -70,7 +67,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenRequestingLastPage_ThenReturnLastPageWithRemData() { + void whenRequestingLastPage_ThenReturnLastPageWithRemData() { Pageable pageRequest = PageRequest.of(2, 2); Page result = productRepository.findAll(pageRequest); @@ -83,7 +80,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenSortingByNameAscAndPaging_ThenReturnSortedPagedResult() { + void whenSortingByNameAscAndPaging_ThenReturnSortedPagedResult() { Pageable pageRequest = PageRequest.of(0, 3, Sort.by("name")); Page result = productRepository.findAll(pageRequest); @@ -97,7 +94,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenSortingByPriceDescAndPaging_ThenReturnSortedPagedResult() { + void whenSortingByPriceDescAndPaging_ThenReturnSortedPagedResult() { Pageable pageRequest = PageRequest.of(0, 3, Sort.by("price") .descending()); @@ -112,7 +109,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenSortingByPriceDescAndNameAscAndPaging_ThenReturnSortedPagedResult() { + void whenSortingByPriceDescAndNameAscAndPaging_ThenReturnSortedPagedResult() { Pageable pageRequest = PageRequest.of(0, 5, Sort.by("price") .descending() .and(Sort.by("name"))); @@ -128,7 +125,7 @@ public class ProductRepositoryIntegrationTest { } @Test - public void whenRequestingFirstPageOfSizeTwoUsingCustomMethod_ThenReturnFirstPage() { + void whenRequestingFirstPageOfSizeTwoUsingCustomMethod_ThenReturnFirstPage() { Pageable pageRequest = PageRequest.of(0, 2); List result = productRepository.findAllByPrice(10, pageRequest); diff --git a/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/projection/JpaProjectionIntegrationTest.java similarity index 67% rename from persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/projection/JpaProjectionIntegrationTest.java index 5fdcf6a787..a112b18721 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/projection/JpaProjectionIntegrationTest.java @@ -1,23 +1,26 @@ -package com.baeldung.projection; - -import com.baeldung.projection.model.Person; -import com.baeldung.projection.repository.AddressRepository; -import com.baeldung.projection.repository.PersonRepository; -import com.baeldung.projection.view.AddressView; -import com.baeldung.projection.view.PersonDto; -import com.baeldung.projection.view.PersonView; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.jdbc.Sql; +package com.baeldung.jpa.projection; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigurationPackage; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.jdbc.Sql; + +import com.baeldung.jpa.projection.model.Person; +import com.baeldung.jpa.projection.repository.AddressRepository; +import com.baeldung.jpa.projection.repository.PersonRepository; +import com.baeldung.jpa.projection.view.AddressView; +import com.baeldung.jpa.projection.view.PersonDto; +import com.baeldung.jpa.projection.view.PersonView; + @DataJpaTest @Sql(scripts = "/projection-insert-data.sql") @Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD) -public class JpaProjectionIntegrationTest { +@AutoConfigurationPackage(basePackages = "com.baeldung.jpa.projection") +class JpaProjectionIntegrationTest { @Autowired private AddressRepository addressRepository; @@ -25,7 +28,7 @@ public class JpaProjectionIntegrationTest { private PersonRepository personRepository; @Test - public void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned() { + void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned() { AddressView addressView = addressRepository.getAddressByState("CA").get(0); assertThat(addressView.getZipCode()).isEqualTo("90001"); @@ -35,20 +38,20 @@ public class JpaProjectionIntegrationTest { } @Test - public void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned() { + void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned() { PersonView personView = personRepository.findByLastName("Doe"); assertThat(personView.getFullName()).isEqualTo("John Doe"); } @Test - public void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned() { + void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned() { PersonDto personDto = personRepository.findByFirstName("John"); assertThat(personDto.getFirstName()).isEqualTo("John"); assertThat(personDto.getLastName()).isEqualTo("Doe"); } @Test - public void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned() { + void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned() { Person person = personRepository.findByLastName("Doe", Person.class); PersonView personView = personRepository.findByLastName("Doe", PersonView.class); PersonDto personDto = personRepository.findByLastName("Doe", PersonDto.class); diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java similarity index 81% rename from persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java index 19760f2bfe..a663408a6b 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java @@ -1,26 +1,28 @@ -package com.baeldung.spring.data.jpa.query; +package com.baeldung.jpa.query; -import org.junit.Test; -import org.junit.runner.RunWith; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigurationPackage; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.JpaSort; import org.springframework.data.mapping.PropertyReferenceException; -import org.springframework.test.context.junit4.SpringRunner; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import com.baeldung.jpa.query.model.User; +import com.baeldung.jpa.query.repository.UserRepository; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@RunWith(SpringRunner.class) @DataJpaTest(properties = "spring.sql.init.data-locations=classpath:insert_users.sql", showSql = false) -public class UserRepositoryIntegrationTest { +@AutoConfigurationPackage(basePackages = "com.baeldung.jpa.query") +class UserQueryRepositoryIntegrationTest { @Autowired private UserRepository userRepository; @@ -40,47 +42,43 @@ public class UserRepositoryIntegrationTest { @Test public void whenFindAllSortedByNameThenAllSorted() { List allUsersSortedByName = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); - assertThat(allUsersSortedByName) - .extracting("name") - .containsSequence("Bob", "Cindy", "John"); + assertThat(allUsersSortedByName).extracting("name") + .containsSequence("Bob", "Cindy", "John"); } @Test public void whenFindAllSortedByNameLengthThenException() { - assertThatThrownBy(() -> userRepository.findAll(Sort.by("LENGTH(name)"))) - .isInstanceOf(PropertyReferenceException.class); + assertThatThrownBy(() -> userRepository.findAll(Sort.by("LENGTH(name)"))).isInstanceOf(PropertyReferenceException.class); } @Test public void whenFindAllUsersSortedByNameThenAllSorted() { List allUsersSortedByName = userRepository.findAllUsers(Sort.by(Sort.Direction.ASC, "name")); - assertThat(allUsersSortedByName) - .extracting("name") - .containsSequence("Bob", "Cindy", "John"); + assertThat(allUsersSortedByName).extracting("name") + .containsSequence("Bob", "Cindy", "John"); } @Test public void whenFindAllUsersSortedByNameLengthThenAllSorted() { List allUsersSortedByName = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); - assertThat(allUsersSortedByName) - .extracting("name") - .containsSequence("Bob", "John", "Cindy"); + assertThat(allUsersSortedByName).extracting("name") + .containsSequence("Bob", "John", "Cindy"); } @Test public void whenFindAllUsersWithPaginationThenPaginated() { Page page = userRepository.findAllUsersWithPagination(PageRequest.of(0, 1)); - assertThat(page.stream().map(User::getId)) - .hasSize(1) - .containsOnly(1); + assertThat(page.stream() + .map(User::getId)).hasSize(1) + .containsOnly(1); } @Test public void whenFindAllUsersWithPaginationNativeThenPaginated() { Page page = userRepository.findAllUsersWithPaginationNative(PageRequest.of(1, 1)); - assertThat(page.stream().map(User::getId)) - .hasSize(1) - .containsOnly(2); + assertThat(page.stream() + .map(User::getId)).hasSize(1) + .containsOnly(2); } @Test @@ -126,9 +124,8 @@ public class UserRepositoryIntegrationTest { @Test public void whenFindUserByNameListThenAllFound() { List users = userRepository.findUserByNameList(Arrays.asList("Bob", "Cindy")); - assertThat(users) - .extracting("name") - .containsOnly("Bob", "Cindy"); + assertThat(users).extracting("name") + .containsOnly("Bob", "Cindy"); } @Test diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java similarity index 70% rename from persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java index d004d485e4..ec2ada1e52 100644 --- a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookListRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java @@ -1,22 +1,24 @@ -package com.baeldung.spring.data.jpa.listrepositories.repository; +package com.baeldung.jpa.simple; + +import java.util.Arrays; +import java.util.List; -import com.baeldung.spring.data.jpa.listrepositories.entity.Book; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.util.Arrays; -import java.util.List; +import com.baeldung.jpa.simple.entity.Book; +import com.baeldung.jpa.simple.repository.BookListRepository; -@SpringBootTest -public class BookListRepositoryIntegrationTest { +@SpringBootTest(classes = JpaApplication.class) +class BookListRepositoryIntegrationTest { @Autowired private BookListRepository bookListRepository; @Test - public void givenDbContainsBooks_whenFindBooksByAuthor_thenReturnBooksByAuthor() { + void givenDbContainsBooks_whenFindBooksByAuthor_thenReturnBooksByAuthor() { Book book1 = new Book("Spring Data", "John Doe", "1234567890"); Book book2 = new Book("Spring Data 2", "John Doe", "1234567891"); Book book3 = new Book("Spring Data 3", "John Doe", "1234567892"); diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java similarity index 76% rename from persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java index 9ea865c04f..d5c8c1bca0 100644 --- a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java @@ -1,7 +1,8 @@ -package com.baeldung.spring.data.jpa.listrepositories.repository; +package com.baeldung.jpa.simple; + +import java.util.Arrays; +import java.util.List; -import com.baeldung.spring.data.jpa.listrepositories.entity.Book; -import com.baeldung.spring.data.jpa.listrepositories.repository.BookPagingAndSortingRepository; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -10,17 +11,17 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import java.util.Arrays; -import java.util.List; +import com.baeldung.jpa.simple.entity.Book; +import com.baeldung.jpa.simple.repository.BookPagingAndSortingRepository; @SpringBootTest -public class BookPagingAndSortingRepositoryIntegrationTest { +class BookPagingAndSortingRepositoryIntegrationTest { @Autowired private BookPagingAndSortingRepository bookPagingAndSortingRepository; @Test - public void givenDbContainsBooks_whenfindBooksByAuthor_thenReturnBooksByAuthor() { + void givenDbContainsBooks_whenfindBooksByAuthor_thenReturnBooksByAuthor() { Book book1 = new Book("Spring Data", "John Miller", "1234567890"); Book book2 = new Book("Spring Data 2", "John Miller", "1234567891"); Book book3 = new Book("Spring Data 3", "John Miller", "1234567892"); diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java new file mode 100644 index 0000000000..7e2dd98ada --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java @@ -0,0 +1,31 @@ +package com.baeldung.jpa.simple; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.jpa.simple.entity.Foo; +import com.baeldung.jpa.simple.service.IFooService; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { JpaApplication.class}) +@DirtiesContext +public class FooServiceIntegrationTest { + + @Autowired + private IFooService service; + + @Autowired + private DataSource dataSource; + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo()); + } +} diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..37afc90b59 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java @@ -0,0 +1,191 @@ +package com.baeldung.jpa.simple; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.baeldung.jpa.simple.entity.User; +import com.baeldung.jpa.simple.repository.UserRepository; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = JpaApplication.class) +class UserRepositoryIntegrationTest { + + private static final String USER_NAME_ADAM = "Adam"; + private static final String USER_NAME_EVE = "Eve"; + private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now(); + + @Autowired + private UserRepository userRepository; + + @BeforeEach + public void setUp() { + + User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true); + User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false); + User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true); + User user4 = new User(null, 30, BIRTHDATE, false); + + userRepository.saveAll(Arrays.asList(user1, user2, user3, user4)); + } + + @AfterEach + public void tearDown() { + + userRepository.deleteAll(); + } + + @Test + void whenFindByName_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByName(USER_NAME_ADAM) + .size()); + } + + @Test + void whenFindByNameIsNull_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameIsNull() + .size()); + } + + @Test + void whenFindByNameNot_thenReturnsCorrectResult() { + + assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM) + .get(0) + .getName()); + } + + @Test + void whenFindByNameStartingWith_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameStartingWith("A") + .size()); + } + + @Test + void whenFindByNameEndingWith_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameEndingWith("e") + .size()); + } + + @Test + void whenByNameContaining_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameContaining("v") + .size()); + } + + @Test + void whenByNameLike_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameEndingWith("m") + .size()); + } + + @Test + void whenByAgeLessThan_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeLessThan(25) + .size()); + } + + @Test + void whenByAgeLessThanEqual_thenReturnsCorrectResult() { + + assertEquals(3, userRepository.findByAgeLessThanEqual(25) + .size()); + } + + @Test + void whenByAgeGreaterThan_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByAgeGreaterThan(25) + .size()); + } + + @Test + void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeGreaterThanEqual(25) + .size()); + } + + @Test + void whenByAgeBetween_thenReturnsCorrectResult() { + + assertEquals(4, userRepository.findByAgeBetween(20, 30) + .size()); + } + + @Test + void whenByBirthDateAfter_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(4, userRepository.findByBirthDateAfter(yesterday) + .size()); + } + + @Test + void whenByBirthDateBefore_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(0, userRepository.findByBirthDateBefore(yesterday) + .size()); + } + + @Test + void whenByActiveTrue_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveTrue() + .size()); + } + + @Test + void whenByActiveFalse_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveFalse() + .size()); + } + + @Test + void whenByAgeIn_thenReturnsCorrectResult() { + + final List ages = Arrays.asList(20, 25); + assertEquals(3, userRepository.findByAgeIn(ages) + .size()); + } + + @Test + void whenByNameOrAge() { + + assertEquals(3, userRepository.findByNameOrAge(USER_NAME_ADAM, 20) + .size()); + } + + @Test + void whenByNameOrAgeAndActive() { + + assertEquals(2, userRepository.findByNameOrAgeAndActive(USER_NAME_ADAM, 20, false) + .size()); + } + + @Test + void whenByNameOrderByName() { + + assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM) + .size()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-simple/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-filtering/src/test/resources/projection-clean-up-data.sql b/persistence-modules/spring-data-jpa-simple/src/test/resources/projection-clean-up-data.sql similarity index 100% rename from persistence-modules/spring-data-jpa-filtering/src/test/resources/projection-clean-up-data.sql rename to persistence-modules/spring-data-jpa-simple/src/test/resources/projection-clean-up-data.sql diff --git a/persistence-modules/spring-data-jpa-filtering/src/test/resources/projection-insert-data.sql b/persistence-modules/spring-data-jpa-simple/src/test/resources/projection-insert-data.sql similarity index 100% rename from persistence-modules/spring-data-jpa-filtering/src/test/resources/projection-insert-data.sql rename to persistence-modules/spring-data-jpa-simple/src/test/resources/projection-insert-data.sql diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/test-aggregation-data.sql b/persistence-modules/spring-data-jpa-simple/src/test/resources/test-aggregation-data.sql similarity index 100% rename from persistence-modules/spring-data-jpa-query/src/test/resources/test-aggregation-data.sql rename to persistence-modules/spring-data-jpa-simple/src/test/resources/test-aggregation-data.sql diff --git a/persistence-modules/spring-data-mongodb-2/src/main/resources/logback.xml b/persistence-modules/spring-data-mongodb-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..08ed142f40 --- /dev/null +++ b/persistence-modules/spring-data-mongodb-2/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-redis/pom.xml b/persistence-modules/spring-data-redis/pom.xml index 382cdf83f5..ff4732926c 100644 --- a/persistence-modules/spring-data-redis/pom.xml +++ b/persistence-modules/spring-data-redis/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -72,12 +72,17 @@ org.apache.maven.plugins maven-surefire-plugin - true - false 0 -Xmx1024m + + org.apache.maven.plugins + maven-compiler-plugin + + true + + @@ -85,7 +90,10 @@ 3.2.4 0.10.0 0.6 - 5.0.2 + 5.1.2 + 3.2.0 + 5.10.2 + com.baeldung.spring.data.redis.SpringRedisApplication \ No newline at end of file diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java index de8e447ef8..7fa82e8f19 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java @@ -14,7 +14,7 @@ import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Configuration public class RedisConfig { @@ -45,7 +45,7 @@ public class RedisConfig { @PreDestroy public void cleanRedis() { - factory.getConnection() + factory.getConnection().serverCommands() .flushDb(); } } diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java index 7fd13d2777..0d7bbe963d 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java @@ -29,9 +29,9 @@ public class RedisConfig { @Bean public RedisTemplate redisTemplate() { - final RedisTemplate template = new RedisTemplate(); + final RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); - template.setValueSerializer(new GenericToStringSerializer(Object.class)); + template.setValueSerializer(new GenericToStringSerializer<>(Object.class)); return template; } diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java index b97ed23387..9da785c158 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java @@ -2,9 +2,11 @@ package com.baeldung.spring.data.redis.model; import java.io.Serializable; +import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisHash; @RedisHash("Student") +@RequiredArgsConstructor public class Student implements Serializable { public enum Gender { diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java index 849e1fb59f..90f2a9d8af 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java @@ -10,7 +10,7 @@ import java.util.List; @Service public class RedisMessageSubscriber implements MessageListener { - public static List messageList = new ArrayList(); + public static List messageList = new ArrayList<>(); public void onMessage(final Message message, final byte[] pattern) { messageList.add(message.toString()); diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java index 2aabe099ea..37b1d9bd54 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java @@ -37,13 +37,13 @@ public class RedisKeyCommandsManualTest { private ReactiveStringCommands stringCommands; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java index 7353b9630c..9569a360fe 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java @@ -34,13 +34,13 @@ public class RedisTemplateListOpsManualTest { private ReactiveListOperations reactiveListOps; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java index af8e41f9e8..df33d362f9 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java @@ -37,13 +37,13 @@ public class RedisTemplateValueOpsManualTest { private ReactiveValueOperations reactiveValueOps; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java index a2b62167a1..8950b582e8 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java @@ -33,18 +33,18 @@ public class StudentRepositoryManualTest { private static redis.embedded.RedisServer redisServer; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } @Test - public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception { + public void whenSavingStudent_thenAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); final Student retrievedStudent = studentRepository.findById(student.getId()).get(); @@ -52,7 +52,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenUpdatingStudent_thenAvailableOnRetrieval() throws Exception { + public void whenUpdatingStudent_thenAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); student.setName("Richard Watson"); @@ -62,7 +62,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenSavingStudents_thenAllShouldAvailableOnRetrieval() throws Exception { + public void whenSavingStudents_thenAllShouldAvailableOnRetrieval() { final Student engStudent = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); final Student medStudent = new Student("Med2015001", "Gareth Houston", Student.Gender.MALE, 2); studentRepository.save(engStudent); @@ -73,7 +73,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenDeletingStudent_thenNotAvailableOnRetrieval() throws Exception { + public void whenDeletingStudent_thenNotAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); studentRepository.deleteById(student.getId()); diff --git a/persistence-modules/spring-jpa-3/.gitignore b/persistence-modules/spring-jpa-3/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/persistence-modules/spring-jpa-3/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/persistence-modules/spring-jpa-3/README.md b/persistence-modules/spring-jpa-3/README.md new file mode 100644 index 0000000000..9db4527148 --- /dev/null +++ b/persistence-modules/spring-jpa-3/README.md @@ -0,0 +1,4 @@ +## Spring JPA (3) + +### Relevant Articles: +- More articles: [[<-- prev]](/spring-jpa-2) diff --git a/persistence-modules/spring-jpa-3/pom.xml b/persistence-modules/spring-jpa-3/pom.xml new file mode 100644 index 0000000000..a249de33ea --- /dev/null +++ b/persistence-modules/spring-jpa-3/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + spring-jpa-3 + 0.1-SNAPSHOT + spring-jpa-3 + war + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + com.h2database + h2 + ${h2.version} + + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + + + + + + 3.2.4 + + + diff --git a/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceRepository.java b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceRepository.java new file mode 100644 index 0000000000..b19ea156ec --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceRepository.java @@ -0,0 +1,128 @@ +package com.baeldung.continuetransactionafterexception; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.continuetransactionafterexception.model.InvoiceEntity; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Query; +import jakarta.persistence.TypedQuery; + +@Repository +public class InvoiceRepository { + private final Logger logger = LoggerFactory.getLogger(InvoiceRepository.class); + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Transactional + public void saveBatch(List invoiceEntities) { + invoiceEntities.forEach(i -> entityManager.persist(i)); + try { + entityManager.flush(); + } catch (Exception e) { + logger.error("Duplicates detected, save individually", e); + + invoiceEntities.forEach(i -> { + try { + save(i); + } catch (Exception ex) { + logger.error("Problem saving individual entity {}", i.getSerialNumber(), ex); + } + }); + } + } + + @Transactional + public void save(InvoiceEntity invoiceEntity) { + if (invoiceEntity.getId() == null) { + entityManager.persist(invoiceEntity); + } else { + entityManager.merge(invoiceEntity); + } + + entityManager.flush(); + logger.info("Entity is saved: {}", invoiceEntity.getSerialNumber()); + } + + public void saveBatchUsingManualTransaction(List testEntities) { + EntityTransaction transaction = null; + try (EntityManager em = em()) { + transaction = em.getTransaction(); + transaction.begin(); + testEntities.forEach(em::persist); + try { + em.flush(); + } catch (Exception e) { + logger.error("Duplicates detected, save individually", e); + transaction.rollback(); + testEntities.forEach(t -> { + EntityTransaction newTransaction = em.getTransaction(); + try { + newTransaction.begin(); + saveUsingManualTransaction(t, em); + } catch (Exception ex) { + logger.error("Problem saving individual entity <{}>", t.getSerialNumber(), ex); + newTransaction.rollback(); + } finally { + commitTransactionIfNeeded(newTransaction); + } + }); + + } + } finally { + commitTransactionIfNeeded(transaction); + } + } + + private void commitTransactionIfNeeded(EntityTransaction newTransaction) { + if (newTransaction != null && newTransaction.isActive()) { + if (!newTransaction.getRollbackOnly()) { + newTransaction.commit(); + } + } + } + + private void saveUsingManualTransaction(InvoiceEntity invoiceEntity, EntityManager em) { + if (invoiceEntity.getId() == null) { + em.persist(invoiceEntity); + } else { + em.merge(invoiceEntity); + } + + em.flush(); + logger.info("Entity is saved: {}", invoiceEntity.getSerialNumber()); + } + + private EntityManager em() { + return entityManagerFactory.createEntityManager(); + } + + @Transactional + public void saveBatchOnly(List testEntities) { + testEntities.forEach(entityManager::persist); + entityManager.flush(); + } + + public List findAll() { + TypedQuery query = entityManager.createQuery("SELECT i From InvoiceEntity i", InvoiceEntity.class); + return query.getResultList(); + } + + @Transactional + public void deleteAll() { + Query query = entityManager.createQuery("DELETE FROM InvoiceEntity"); + query.executeUpdate(); + } +} diff --git a/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceService.java b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceService.java new file mode 100644 index 0000000000..e1db310d03 --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/InvoiceService.java @@ -0,0 +1,27 @@ +package com.baeldung.continuetransactionafterexception; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.continuetransactionafterexception.model.InvoiceEntity; + +@Service +public class InvoiceService { + @Autowired + private InvoiceRepository repository; + @Transactional + public void saveInvoice(InvoiceEntity invoice) { + repository.save(invoice); + sendNotification(); + } + @Transactional(noRollbackFor = NotificationSendingException.class) + public void saveInvoiceWithoutRollback(InvoiceEntity entity) { + repository.save(entity); + sendNotification(); + } + + private void sendNotification() { + throw new NotificationSendingException("Notification sending is failed"); + } +} diff --git a/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/NotificationSendingException.java b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/NotificationSendingException.java new file mode 100644 index 0000000000..8c2fd3cd5b --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/NotificationSendingException.java @@ -0,0 +1,8 @@ +package com.baeldung.continuetransactionafterexception; + +public class NotificationSendingException extends RuntimeException { + + public NotificationSendingException(String text) { + super(text); + } +} diff --git a/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/model/InvoiceEntity.java b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/model/InvoiceEntity.java new file mode 100644 index 0000000000..bcae12b2ab --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/main/java/com/baeldung/continuetransactionafterexception/model/InvoiceEntity.java @@ -0,0 +1,62 @@ +package com.baeldung.continuetransactionafterexception.model; + +import java.util.Objects; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + +@Entity +@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "serialNumber")}) +public class InvoiceEntity { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Integer id; + private String serialNumber; + private String description; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getSerialNumber() { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InvoiceEntity that = (InvoiceEntity) o; + return Objects.equals(serialNumber, that.serialNumber); + } + + @Override + public int hashCode() { + return Objects.hash(serialNumber); + } +} diff --git a/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationConfiguration.java b/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationConfiguration.java new file mode 100644 index 0000000000..3a5bd1cde2 --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationConfiguration.java @@ -0,0 +1,61 @@ +package com.baeldung.com.baeldung.continuetransactionafterexception; + +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +import jakarta.persistence.EntityManagerFactory; + +@Configuration +@PropertySource("continuetransactionafterexception/test.properties") +public class ContinueWithTransactionAfterExceptionIntegrationConfiguration { + + @Bean + public DataSource dataSource() { + EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder(); + return dbBuilder.setType(EmbeddedDatabaseType.H2) + .build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Value("${hibernate.hbm2ddl.auto}") String hbm2ddlType, @Value("${hibernate.dialect}") String dialect, @Value("${hibernate.show_sql}") boolean showSql) { + LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean(); + + result.setDataSource(dataSource()); + result.setPackagesToScan("com.baeldung.continuetransactionafterexception.model"); + result.setJpaVendorAdapter(jpaVendorAdapter()); + + Map jpaProperties = new HashMap<>(); + jpaProperties.put("hibernate.hbm2ddl.auto", hbm2ddlType); + jpaProperties.put("hibernate.dialect", dialect); + jpaProperties.put("hibernate.show_sql", showSql); + result.setJpaPropertyMap(jpaProperties); + + return result; + } + + @Bean + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory); + transactionManager.setNestedTransactionAllowed(true); + + return transactionManager; + } + + public JpaVendorAdapter jpaVendorAdapter() { + return new HibernateJpaVendorAdapter(); + } +} diff --git a/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationTest.java b/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationTest.java new file mode 100644 index 0000000000..7f5f60f556 --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/test/java/com/baeldung/com/baeldung/continuetransactionafterexception/ContinueWithTransactionAfterExceptionIntegrationTest.java @@ -0,0 +1,165 @@ +package com.baeldung.com.baeldung.continuetransactionafterexception; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.UnexpectedRollbackException; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.baeldung.continuetransactionafterexception.InvoiceRepository; +import com.baeldung.continuetransactionafterexception.InvoiceService; +import com.baeldung.continuetransactionafterexception.NotificationSendingException; +import com.baeldung.continuetransactionafterexception.model.InvoiceEntity; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + ContinueWithTransactionAfterExceptionIntegrationConfiguration.class, + InvoiceRepository.class, InvoiceService.class}) +@DirtiesContext +@EnableTransactionManagement +class ContinueWithTransactionAfterExceptionIntegrationTest { + + @Autowired + private InvoiceRepository repository; + @Autowired + private InvoiceService service; + + @Test + void givenInvoiceService_whenExceptionOccursDuringNotificationSending_thenNoDataShouldBeSaved() { + InvoiceEntity invoiceEntity = new InvoiceEntity(); + invoiceEntity.setSerialNumber("#1"); + invoiceEntity.setDescription("First invoice"); + + assertThrows( + NotificationSendingException.class, + () -> service.saveInvoice(invoiceEntity) + ); + + List entityList = repository.findAll(); + Assertions.assertTrue(entityList.isEmpty()); + } + + @Test + void givenInvoiceRepository_whenExceptionOccursDuringBatchSavingInternally_thenNoDataShouldBeSaved() { + + List testEntities = new ArrayList<>(); + + InvoiceEntity invoiceEntity = new InvoiceEntity(); + invoiceEntity.setSerialNumber("#1"); + invoiceEntity.setDescription("First invoice"); + testEntities.add(invoiceEntity); + + InvoiceEntity invoiceEntity2 = new InvoiceEntity(); + invoiceEntity2.setSerialNumber("#1"); + invoiceEntity.setDescription("First invoice (duplicated)"); + testEntities.add(invoiceEntity2); + + InvoiceEntity invoiceEntity3 = new InvoiceEntity(); + invoiceEntity3.setSerialNumber("#2"); + invoiceEntity.setDescription("Second invoice"); + testEntities.add(invoiceEntity3); + + UnexpectedRollbackException exception = assertThrows(UnexpectedRollbackException.class, + () -> repository.saveBatch(testEntities)); + assertEquals("Transaction silently rolled back because it has been marked as rollback-only", + exception.getMessage()); + + List entityList = repository.findAll(); + Assertions.assertTrue(entityList.isEmpty()); + } + + @Test + void givenInvoiceService_whenNotificationSendingExceptionOccurs_thenTheInvoiceBeSaved() { + InvoiceEntity invoiceEntity = new InvoiceEntity(); + invoiceEntity.setSerialNumber("#1"); + invoiceEntity.setDescription("We want to save this invoice anyway"); + + assertThrows( + NotificationSendingException.class, + () -> service.saveInvoiceWithoutRollback(invoiceEntity) + ); + + List entityList = repository.findAll(); + Assertions.assertTrue(entityList.contains(invoiceEntity)); + } + + @Test + void givenInvoiceRepository_whenExceptionOccursDuringBatchSavingInternally_thenDataShouldBeSavedInSeparateTransaction() { + + List testEntities = new ArrayList<>(); + + InvoiceEntity invoiceEntity1 = new InvoiceEntity(); + invoiceEntity1.setSerialNumber("#1"); + invoiceEntity1.setDescription("First invoice"); + testEntities.add(invoiceEntity1); + + InvoiceEntity invoiceEntity2 = new InvoiceEntity(); + invoiceEntity2.setSerialNumber("#1"); + invoiceEntity1.setDescription("First invoice (duplicated)"); + testEntities.add(invoiceEntity2); + + InvoiceEntity invoiceEntity3 = new InvoiceEntity(); + invoiceEntity3.setSerialNumber("#2"); + invoiceEntity1.setDescription("Second invoice"); + testEntities.add(invoiceEntity3); + + repository.saveBatchUsingManualTransaction(testEntities); + + List entityList = repository.findAll(); + Assertions.assertTrue(entityList.contains(invoiceEntity1)); + Assertions.assertTrue(entityList.contains(invoiceEntity3)); + } + + @Test + void givenInvoiceRepository_whenExceptionOccursDuringBatchSaving_thenDataShouldBeSavedUsingSaveMethod() { + + List testEntities = new ArrayList<>(); + + InvoiceEntity invoiceEntity1 = new InvoiceEntity(); + invoiceEntity1.setSerialNumber("#1"); + invoiceEntity1.setDescription("First invoice"); + testEntities.add(invoiceEntity1); + + InvoiceEntity invoiceEntity2 = new InvoiceEntity(); + invoiceEntity2.setSerialNumber("#1"); + invoiceEntity1.setDescription("First invoice (duplicated)"); + testEntities.add(invoiceEntity2); + + InvoiceEntity invoiceEntity3 = new InvoiceEntity(); + invoiceEntity3.setSerialNumber("#2"); + invoiceEntity1.setDescription("Second invoice"); + testEntities.add(invoiceEntity3); + + try { + repository.saveBatchOnly(testEntities); + } catch (Exception e) { + testEntities.forEach(t -> { + try { + repository.save(t); + } catch (Exception e2) { + System.err.println(e2.getMessage()); + } + }); + } + + List entityList = repository.findAll(); + Assertions.assertTrue(entityList.contains(invoiceEntity1)); + Assertions.assertTrue(entityList.contains(invoiceEntity3)); + } + + @AfterEach + void clean() { + repository.deleteAll(); + } +} diff --git a/persistence-modules/spring-jpa-3/src/test/resources/continuetransactionafterexception/test.properties b/persistence-modules/spring-jpa-3/src/test/resources/continuetransactionafterexception/test.properties new file mode 100644 index 0000000000..191dfc85f5 --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/test/resources/continuetransactionafterexception/test.properties @@ -0,0 +1,7 @@ +jdbc.driverClassName=org.h2.Driver +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=update diff --git a/persistence-modules/spring-jpa-3/src/test/resources/logback.xml b/persistence-modules/spring-jpa-3/src/test/resources/logback.xml new file mode 100644 index 0000000000..4ecb8017f3 --- /dev/null +++ b/persistence-modules/spring-jpa-3/src/test/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + diff --git a/pom.xml b/pom.xml index 74ad74e63b..7496d4ca93 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,9 @@ **/JdbcTest.java **/*LiveTest.java + + ${tutorialsproject.basedir}/${logback.configurationFileName} + @@ -231,7 +234,7 @@ - com.vackosar.gitflowincrementalbuilder + io.github.gitflow-incremental-builder gitflow-incremental-builder ${gitflow-incremental-builder.version} @@ -318,9 +321,6 @@ **/JdbcTest.java **/*LiveTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -388,9 +388,6 @@ **/*JdbcTest.java **/*LiveTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -471,9 +468,6 @@ **/*IntegrationTest.java **/*IntTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -530,9 +524,6 @@ **/*IntegrationTest.java **/*IntTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -660,6 +651,7 @@ apache-httpclient4 apache-httpclient apache-kafka-2 + apache-kafka-3 apache-kafka apache-libraries-2 apache-libraries @@ -682,7 +674,6 @@ di-modules disruptor docker-modules - dozer drools dubbo feign @@ -755,7 +746,7 @@ lombok-modules lucene mapstruct - + maven-modules mesos-marathon messaging-modules metrics @@ -805,6 +796,7 @@ spring-cloud-modules/spring-cloud-security spring-cloud-modules/spring-cloud-zuul-eureka-integration + spring-cloud-modules/spring-cloud-bootstrap spring-core-2 spring-core-3 spring-core-4 @@ -825,14 +817,14 @@ spring-kafka-2 spring-kafka-3 spring-kafka - spring-katharsis + spring-katharsis spring-mobile spring-native spring-protobuf spring-pulsar spring-quartz spring-reactive-modules - spring-remoting-modules + spring-remoting-modules spring-scheduling spring-security-modules spring-shell @@ -906,6 +898,7 @@ apache-httpclient4 apache-httpclient apache-kafka-2 + apache-kafka-3 apache-kafka apache-libraries-2 apache-libraries @@ -928,7 +921,6 @@ di-modules disruptor docker-modules - dozer drools dubbo feign @@ -1002,7 +994,7 @@ lombok-modules lucene mapstruct - + maven-modules mesos-marathon messaging-modules metrics @@ -1052,6 +1044,7 @@ spring-cloud-modules/spring-cloud-security spring-cloud-modules/spring-cloud-zuul-eureka-integration + spring-cloud-modules/spring-cloud-bootstrap spring-core-2 spring-core-3 spring-core-4 @@ -1072,14 +1065,14 @@ spring-kafka-2 spring-kafka-3 spring-kafka - spring-katharsis + spring-katharsis spring-mobile spring-native spring-protobuf spring-pulsar spring-quartz spring-reactive-modules - spring-remoting-modules + spring-remoting-modules spring-scheduling spring-security-modules spring-shell @@ -1149,6 +1142,7 @@ false false true + .*gradle-modules.* 4.13.2 @@ -1189,13 +1183,15 @@ 1.0 3.1.1 0.0.1 - 3.12.2 + 4.5.3 3.3.0 3.21.0 1.18.30 - 2.1.214 + 2.2.224 33.0.0-jre 3.3.0 + + logback-config-global.xml diff --git a/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml b/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml index f1fe9eec5c..c5f8080c38 100644 --- a/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml +++ b/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml @@ -66,7 +66,7 @@ - 4.25.0 + 4.26.0 \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml index fc24b43497..f087fbba6b 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml @@ -7,9 +7,9 @@ 0.1-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 3.1.3 + com.baeldung + quarkus-vs-springboot + 1.0-SNAPSHOT @@ -21,6 +21,13 @@ pom import + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + @@ -93,6 +100,7 @@ 17 1.17.2 1.0.2 + 3.1.3 \ No newline at end of file diff --git a/reactive-systems/inventory-service/pom.xml b/reactive-systems/inventory-service/pom.xml index baf5151fdc..0d9556850c 100644 --- a/reactive-systems/inventory-service/pom.xml +++ b/reactive-systems/inventory-service/pom.xml @@ -26,6 +26,7 @@ org.springframework.kafka spring-kafka + ${spring-kafka.version} org.projectlombok diff --git a/reactive-systems/order-service/pom.xml b/reactive-systems/order-service/pom.xml index b6cfb70678..6ef4a9dd8f 100644 --- a/reactive-systems/order-service/pom.xml +++ b/reactive-systems/order-service/pom.xml @@ -26,6 +26,7 @@ org.springframework.kafka spring-kafka + ${spring-kafka.version} org.projectlombok diff --git a/reactive-systems/pom.xml b/reactive-systems/pom.xml index b984fc7cd8..d84e07696d 100644 --- a/reactive-systems/pom.xml +++ b/reactive-systems/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -21,4 +21,8 @@ order-service + + 3.1.2 + + \ No newline at end of file diff --git a/reactive-systems/shipping-service/pom.xml b/reactive-systems/shipping-service/pom.xml index 8f94dabdea..888cd08c0c 100644 --- a/reactive-systems/shipping-service/pom.xml +++ b/reactive-systems/shipping-service/pom.xml @@ -22,6 +22,7 @@ org.springframework.kafka spring-kafka + ${spring-kafka.version} com.fasterxml.jackson.core diff --git a/rxjava-modules/pom.xml b/rxjava-modules/pom.xml index 7bdfd0a9c1..e7c0b88613 100644 --- a/rxjava-modules/pom.xml +++ b/rxjava-modules/pom.xml @@ -49,11 +49,6 @@ awaitility ${awaitility.version} - - com.google.guava - guava - ${guava.version} - diff --git a/rxjava-modules/rxjava-core/pom.xml b/rxjava-modules/rxjava-core/pom.xml index 73ab98288d..247d64cc5c 100644 --- a/rxjava-modules/rxjava-core/pom.xml +++ b/rxjava-modules/rxjava-core/pom.xml @@ -13,4 +13,12 @@ 0.0.1-SNAPSHOT + + + com.google.guava + guava + ${guava.version} + + + \ No newline at end of file diff --git a/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java b/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java index 9bdee7f732..0ce558f9e0 100644 --- a/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java +++ b/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java @@ -1,6 +1,7 @@ package com.baeldung.cfuaa.oauth2.resourceserver; import org.springframework.context.annotation.Bean; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @@ -10,16 +11,14 @@ public class CFUAAOAuth2ResourceServerSecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/read/**") + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/read/**") .hasAuthority("SCOPE_resource.read") - .antMatchers("/write/**") + .requestMatchers("/write/**") .hasAuthority("SCOPE_resource.write") .anyRequest() - .authenticated() - .and() - .oauth2ResourceServer() - .jwt(); + .authenticated()) + .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } diff --git a/security-modules/cloud-foundry-uaa/pom.xml b/security-modules/cloud-foundry-uaa/pom.xml index ff26d56dc3..4ba70fbd43 100644 --- a/security-modules/cloud-foundry-uaa/pom.xml +++ b/security-modules/cloud-foundry-uaa/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 diff --git a/security-modules/sql-injection-samples/pom.xml b/security-modules/sql-injection-samples/pom.xml index 37779e0d14..f842c0af0a 100644 --- a/security-modules/sql-injection-samples/pom.xml +++ b/security-modules/sql-injection-samples/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -25,6 +25,11 @@ derby runtime + + org.apache.derby + derbytools + runtime + org.springframework.boot spring-boot-configuration-processor @@ -46,8 +51,9 @@ spring-boot-starter-data-jpa - org.hibernate + org.hibernate.orm hibernate-jpamodelgen + ${hibernate-jpamodelgen.version} org.springframework.boot @@ -64,4 +70,9 @@ + + 17 + 6.4.4.Final + + \ No newline at end of file diff --git a/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java b/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java index 3f077d5592..a2bb1765f2 100644 --- a/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java +++ b/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java @@ -5,11 +5,11 @@ package com.baeldung.examples.security.sql; import java.math.BigDecimal; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import lombok.Data; diff --git a/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java index c7285e5fd3..e273924031 100644 --- a/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java +++ b/security-modules/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -9,7 +9,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -17,18 +16,17 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.persistence.EntityManager; -import javax.persistence.Query; -import javax.persistence.TypedQuery; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Root; -import javax.persistence.metamodel.SingularAttribute; import javax.sql.DataSource; import org.springframework.stereotype.Component; +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.metamodel.SingularAttribute; + /** * @author Philippe * diff --git a/security-modules/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/security-modules/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java index f61b738abc..ba0bc09343 100644 --- a/security-modules/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java +++ b/security-modules/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -75,7 +75,7 @@ public class SqlInjectionSamplesApplicationUnitTest { } @Test(expected = IllegalArgumentException.class) - public void givenASafeMethod_whenInvalidOrderBy_thenThroweException() { + public void givenASafeMethod_whenInvalidOrderBy_thenThrowException() { target.safeFindAccountsByCustomerId("C1", "INVALID"); } diff --git a/security-modules/sql-injection-samples/src/test/resources/application-test.yml b/security-modules/sql-injection-samples/src/test/resources/application-test.yml index 3af3f58bff..4c5d6bd853 100644 --- a/security-modules/sql-injection-samples/src/test/resources/application-test.yml +++ b/security-modules/sql-injection-samples/src/test/resources/application-test.yml @@ -11,7 +11,8 @@ spring: datasource: initialization-mode: embedded - + driver-class-name: org.apache.derby.jdbc.EmbeddedDriver + logging: level: sql: DEBUG diff --git a/server-modules/undertow/pom.xml b/server-modules/undertow/pom.xml index a73771485c..8baf69c88a 100644 --- a/server-modules/undertow/pom.xml +++ b/server-modules/undertow/pom.xml @@ -32,6 +32,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/server-modules/wildfly/pom.xml b/server-modules/wildfly/pom.xml index fece3c9866..bc02f42b98 100644 --- a/server-modules/wildfly/pom.xml +++ b/server-modules/wildfly/pom.xml @@ -51,6 +51,7 @@ maven-failsafe-plugin + ${maven-failsafe-plugin.version} diff --git a/spf4j/spf4j-aspects-app/pom.xml b/spf4j/spf4j-aspects-app/pom.xml index 9769ff77f3..df3b0ee551 100644 --- a/spf4j/spf4j-aspects-app/pom.xml +++ b/spf4j/spf4j-aspects-app/pom.xml @@ -77,6 +77,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/spf4j/spf4j-core-app/pom.xml b/spf4j/spf4j-core-app/pom.xml index ee82ea869a..665b37583c 100644 --- a/spf4j/spf4j-core-app/pom.xml +++ b/spf4j/spf4j-core-app/pom.xml @@ -83,6 +83,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/spring-5-webflux-2/pom.xml b/spring-5-webflux-2/pom.xml index 38cbbc8bf0..2bc981f9db 100644 --- a/spring-5-webflux-2/pom.xml +++ b/spring-5-webflux-2/pom.xml @@ -10,30 +10,11 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 - - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - - org.springframework.boot @@ -110,14 +91,6 @@ org.springframework.boot spring-boot-maven-plugin - - org.apache.maven.plugins - maven-compiler-plugin - - 16 - 16 - - @@ -126,6 +99,9 @@ 3.1.8 1.16.2 5.0.0-alpha.12 + true + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-5-webflux-2/src/main/resources/logback.xml b/spring-5-webflux-2/src/main/resources/logback.xml index 48b68c6bf1..a81845477f 100644 --- a/spring-5-webflux-2/src/main/resources/logback.xml +++ b/spring-5-webflux-2/src/main/resources/logback.xml @@ -1,12 +1,9 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + diff --git a/spring-5-webflux-2/src/test/resources/logback-test.xml b/spring-5-webflux-2/src/test/resources/logback-test.xml index 12cedf5952..254798dc62 100644 --- a/spring-5-webflux-2/src/test/resources/logback-test.xml +++ b/spring-5-webflux-2/src/test/resources/logback-test.xml @@ -1,12 +1,5 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - - diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index 62a463a5cd..f0de0e5dcb 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -90,12 +90,22 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + + true + + 5.0.0-alpha.12 2.0.0-Beta4 + true + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java index bc4f628ab1..121608e7c2 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java @@ -18,18 +18,18 @@ import static org.springframework.web.reactive.function.server.RequestPredicates @RestController public class ResponseStatusController { - @GetMapping(value = "/ok", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/ok", produces = MediaType.APPLICATION_JSON_VALUE) public Flux ok() { return Flux.just("ok"); } - @GetMapping(value = "/no-content", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/no-content", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.NO_CONTENT) public Flux noContent() { return Flux.empty(); } - @GetMapping(value = "/accepted", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/accepted", produces = MediaType.APPLICATION_JSON_VALUE) public Flux accepted(ServerHttpResponse response) { response.setStatusCode(HttpStatus.ACCEPTED); return Flux.just("accepted"); diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java b/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java index baace095a7..597831b7e6 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java @@ -3,6 +3,7 @@ package com.baeldung.spring.retry; import java.time.Duration; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -24,7 +25,7 @@ public class ExternalConnector { .uri(PATH_BY_ID, stockId) .accept(MediaType.APPLICATION_JSON) .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new ServiceException("Server error", response.rawStatusCode()))) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.error(new ServiceException("Server error", response.statusCode().value()))) .bodyToMono(String.class) .retryWhen(Retry.backoff(3, Duration.ofSeconds(2)) .filter(throwable -> throwable instanceof ServiceException) diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java index cf4e5ac8ea..9ee722cb55 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java @@ -20,7 +20,7 @@ public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCusto ssl.setKeyStorePassword("secret"); Http2 http2 = new Http2(); http2.setEnabled(false); - serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null)); + serverFactory.addServerCustomizers(new SslServerCustomizer(http2, ssl.getClientAuth(), null)); serverFactory.setPort(8443); } } diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java index a4cd6bd6ba..3f0c004d6c 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java @@ -14,7 +14,7 @@ public class TimeoutController { @GetMapping("/{timeout}") private Mono timeout(@PathVariable int timeout) { try { - Thread.sleep(timeout * 1000); + Thread.sleep(timeout * 1000L); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } diff --git a/spring-5-webflux/src/main/resources/logback.xml b/spring-5-webflux/src/main/resources/logback.xml index 48b68c6bf1..a81845477f 100644 --- a/spring-5-webflux/src/main/resources/logback.xml +++ b/spring-5-webflux/src/main/resources/logback.xml @@ -1,12 +1,9 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + diff --git a/spring-5-webflux/src/test/resources/logback-test.xml b/spring-5-webflux/src/test/resources/logback-test.xml index 12cedf5952..c1df08bdb5 100644 --- a/spring-5-webflux/src/test/resources/logback-test.xml +++ b/spring-5-webflux/src/test/resources/logback-test.xml @@ -1,12 +1,11 @@ - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + + diff --git a/spring-5/README.md b/spring-5/README.md index 6649a392db..d1487913ac 100644 --- a/spring-5/README.md +++ b/spring-5/README.md @@ -11,3 +11,4 @@ This module contains articles about Spring 5 - [Spring Assert Statements](https://www.baeldung.com/spring-assert) - [Difference between context:annotation-config vs context:component-scan](https://www.baeldung.com/spring-contextannotation-contextcomponentscan) - [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) +- [Document Query Parameters with Spring REST Docs](https://www.baeldung.com/spring-rest-document-query-parameters) diff --git a/spring-5/pom.xml b/spring-5/pom.xml index c41b8aa301..d66f0fa01f 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -42,17 +42,25 @@ spring-boot-starter-webflux - javax.json.bind - javax.json.bind-api + jakarta.json.bind + jakarta.json.bind-api org.apache.geronimo.specs geronimo-json_1.1_spec ${geronimo-json_1.1_spec.version} + + + jakarta.json + jakarta.json-api + ${jakarta.json-api.version} + + org.apache.johnzon johnzon-jsonb + ${johnzon-jsonb.version} @@ -151,9 +159,12 @@ 1.0 - 1.5.6 + 2.2.6 ${project.build.directory}/generated-snippets 5.1.0 + true + 2.0.1 + 2.0.0 \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/assertions/Car.java b/spring-5/src/main/java/com/baeldung/assertions/Car.java index abff27f0b0..d0153ce528 100644 --- a/spring-5/src/main/java/com/baeldung/assertions/Car.java +++ b/spring-5/src/main/java/com/baeldung/assertions/Car.java @@ -109,11 +109,11 @@ public class Car { car.startWithHasText("t"); car.startWithNotContain("132"); - List repairPartsCollection = new ArrayList(); + List repairPartsCollection = new ArrayList<>(); repairPartsCollection.add("part"); car.repair(repairPartsCollection); - Map repairPartsMap = new HashMap(); + Map repairPartsMap = new HashMap<>(); repairPartsMap.put("1", "part"); car.repair(repairPartsMap); diff --git a/spring-5/src/main/java/com/baeldung/jsonb/Person.java b/spring-5/src/main/java/com/baeldung/jsonb/Person.java index 7a54b37574..1c495f05bd 100644 --- a/spring-5/src/main/java/com/baeldung/jsonb/Person.java +++ b/spring-5/src/main/java/com/baeldung/jsonb/Person.java @@ -3,10 +3,10 @@ package com.baeldung.jsonb; import java.math.BigDecimal; import java.time.LocalDate; -import javax.json.bind.annotation.JsonbDateFormat; -import javax.json.bind.annotation.JsonbNumberFormat; -import javax.json.bind.annotation.JsonbProperty; -import javax.json.bind.annotation.JsonbTransient; +import jakarta.json.bind.annotation.JsonbDateFormat; +import jakarta.json.bind.annotation.JsonbNumberFormat; +import jakarta.json.bind.annotation.JsonbProperty; +import jakarta.json.bind.annotation.JsonbTransient; public class Person { diff --git a/spring-5/src/main/java/com/baeldung/jsonb/PersonController.java b/spring-5/src/main/java/com/baeldung/jsonb/PersonController.java index e216a282eb..f69fcf4795 100644 --- a/spring-5/src/main/java/com/baeldung/jsonb/PersonController.java +++ b/spring-5/src/main/java/com/baeldung/jsonb/PersonController.java @@ -6,7 +6,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; diff --git a/spring-5/src/main/java/com/baeldung/restdocs/CRUDController.java b/spring-5/src/main/java/com/baeldung/restdocs/CRUDController.java index b10cfd5f55..b92e23f757 100644 --- a/spring-5/src/main/java/com/baeldung/restdocs/CRUDController.java +++ b/spring-5/src/main/java/com/baeldung/restdocs/CRUDController.java @@ -5,7 +5,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import java.util.ArrayList; import java.util.List; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -53,7 +53,7 @@ public class CRUDController { @PatchMapping("/{id}") public List patch(@PathVariable("id") long id, @RequestBody CrudInput crudInput) { - List returnList = new ArrayList(); + List returnList = new ArrayList<>(); crudInput.setId(id); returnList.add(crudInput); return returnList; diff --git a/spring-5/src/main/java/com/baeldung/restdocs/CrudInput.java b/spring-5/src/main/java/com/baeldung/restdocs/CrudInput.java index 29046d7725..4e783150d5 100644 --- a/spring-5/src/main/java/com/baeldung/restdocs/CrudInput.java +++ b/spring-5/src/main/java/com/baeldung/restdocs/CrudInput.java @@ -4,8 +4,8 @@ import java.net.URI; import java.util.Collections; import java.util.List; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/spring-5/src/main/java/com/baeldung/web/Foo.java b/spring-5/src/main/java/com/baeldung/web/Foo.java index c4868a9958..ca058652a5 100644 --- a/spring-5/src/main/java/com/baeldung/web/Foo.java +++ b/spring-5/src/main/java/com/baeldung/web/Foo.java @@ -1,9 +1,9 @@ package com.baeldung.web; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; @Entity public class Foo { diff --git a/spring-5/src/main/java/com/baeldung/web/FooController.java b/spring-5/src/main/java/com/baeldung/web/FooController.java index a09e628421..23c258c3c7 100644 --- a/spring-5/src/main/java/com/baeldung/web/FooController.java +++ b/spring-5/src/main/java/com/baeldung/web/FooController.java @@ -7,9 +7,9 @@ import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.annotation.PostConstruct; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; +import jakarta.annotation.PostConstruct; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import java.util.List; @RestController("/foos") diff --git a/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationIntegrationTest.java index 9c462e0412..2e5a1d6d04 100644 --- a/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationIntegrationTest.java @@ -20,21 +20,21 @@ public class BeanRegistrationIntegrationTest { @Test public void whenRegisterBean_thenOk() { - context.registerBean(MyService.class, () -> new MyService()); + context.registerBean(MyService.class, MyService::new); MyService myService = (MyService) context.getBean("com.baeldung.functional.MyService"); assertTrue(myService.getRandomNumber() < 10); } @Test public void whenRegisterBeanWithName_thenOk() { - context.registerBean("mySecondService", MyService.class, () -> new MyService()); + context.registerBean("mySecondService", MyService.class, MyService::new); MyService mySecondService = (MyService) context.getBean("mySecondService"); assertTrue(mySecondService.getRandomNumber() < 10); } @Test public void whenRegisterBeanWithCallback_thenOk() { - context.registerBean("myCallbackService", MyService.class, () -> new MyService(), bd -> bd.setAutowireCandidate(false)); + context.registerBean("myCallbackService", MyService.class, MyService::new, bd -> bd.setAutowireCandidate(false)); MyService myCallbackService = (MyService) context.getBean("myCallbackService"); assertTrue(myCallbackService.getRandomNumber() < 10); } diff --git a/spring-5/src/test/java/com/baeldung/jsonb/JsonbIntegrationTest.java b/spring-5/src/test/java/com/baeldung/jsonb/JsonbIntegrationTest.java index f4749c0d33..14870460e4 100644 --- a/spring-5/src/test/java/com/baeldung/jsonb/JsonbIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/jsonb/JsonbIntegrationTest.java @@ -9,7 +9,6 @@ import org.junit.Ignore; 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.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.ResponseEntity; diff --git a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerMvcIntegrationTest.java b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerMvcIntegrationTest.java index ab96364e6a..3172a06ca1 100644 --- a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerMvcIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerMvcIntegrationTest.java @@ -7,7 +7,7 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.pr import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; @@ -50,6 +50,6 @@ class BookControllerMvcIntegrationTest { mockMvc.perform(get("/books?page=2")) .andExpect(status().isOk()) .andDo(document("books", - requestParameters(parameterWithName("page").description("The page to retrieve")))); + queryParameters(parameterWithName("page").description("The page to retrieve")))); } } \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerReactiveIntegrationTest.java b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerReactiveIntegrationTest.java index b2a6991f27..fdbad44480 100644 --- a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerReactiveIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerReactiveIntegrationTest.java @@ -2,7 +2,7 @@ package com.baeldung.queryparamdoc; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document; import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration; @@ -46,7 +46,7 @@ class BookControllerReactiveIntegrationTest { webTestClient.get().uri("/books?page=2") .exchange().expectStatus().isOk().expectBody() .consumeWith(document("books", - requestParameters(parameterWithName("page").description("The page to retrieve")))); + queryParameters(parameterWithName("page").description("The page to retrieve")))); } @TestConfiguration diff --git a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerRestAssuredIntegrationTest.java b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerRestAssuredIntegrationTest.java index 44c6b27285..e24a626114 100644 --- a/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerRestAssuredIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/queryparamdoc/BookControllerRestAssuredIntegrationTest.java @@ -3,9 +3,7 @@ package com.baeldung.queryparamdoc; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.core.Is.is; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; -import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; -import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; @@ -19,6 +17,7 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.restdocs.restassured.RestAssuredRestDocumentation; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -31,7 +30,7 @@ class BookControllerRestAssuredIntegrationTest { @BeforeEach void setUp(RestDocumentationContextProvider restDocumentation, @LocalServerPort int port) { - this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(restDocumentation)) + this.spec = new RequestSpecBuilder().addFilter(RestAssuredRestDocumentation.documentationConfiguration(restDocumentation)) .setPort(port) .build(); } @@ -44,7 +43,7 @@ class BookControllerRestAssuredIntegrationTest { @Test @WithMockUser void givenEndpoint_whenSendGetRequest_thenSuccessfulResponse() { - RestAssured.given(this.spec).filter(document("users", requestParameters( + RestAssured.given(this.spec).filter(RestAssuredRestDocumentation.document("users", queryParameters( parameterWithName("page").description("The page to retrieve")))) .when().get("/books?page=2") .then().assertThat().statusCode(is(200)); diff --git a/spring-activiti/pom.xml b/spring-activiti/pom.xml index ced1d74103..c0b13c7fff 100644 --- a/spring-activiti/pom.xml +++ b/spring-activiti/pom.xml @@ -10,11 +10,19 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 + + + alfresco + alfresco + https://artifacts.alfresco.com/nexus/content/repositories/public/ + + + org.activiti @@ -59,7 +67,7 @@ - 7.1.0.M6 + 8.0.0 \ No newline at end of file diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java index f9394742cd..f0c5e95ca5 100644 --- a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java @@ -3,11 +3,11 @@ package com.baeldung.activiti.security.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc -public class MvcConfig extends WebMvcConfigurerAdapter { +public class MvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java index 8dc3eee05e..6f3885a7ed 100644 --- a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java @@ -3,6 +3,7 @@ package com.baeldung.activiti.security.withspring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -14,28 +15,25 @@ public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.antMatcher("/**") - .authorizeRequests() - .antMatchers("/protected-process*") - .authenticated() - .anyRequest() - .permitAll() - .and() - .formLogin() - .loginPage("/login") - .defaultSuccessUrl("/homepage") - .failureUrl("/login?error=true") - .and() - .csrf() - .disable() - .logout() - .logoutSuccessUrl("/login"); + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/protected-process*") + .authenticated() + .anyRequest() + .permitAll()) + .formLogin(login -> login + .loginPage("/login") + .defaultSuccessUrl("/homepage") + .failureUrl("/login?error=true") + .permitAll()) + .csrf(AbstractHttpConfigurer::disable) + .logout(logout -> logout.logoutSuccessUrl("/login")); return http.build(); } @Bean public UserDetailsService userDetailsService() { - UserDetails user = User.withUsername("user") + User.UserBuilder users = User.withDefaultPasswordEncoder(); + UserDetails user = users.username("user") .password("{noop}pass") .authorities("ROLE_ACTIVITI_USER") .build(); diff --git a/spring-activiti/src/main/resources/templates/homepage.html b/spring-activiti/src/main/resources/templates/homepage.html new file mode 100644 index 0000000000..68a7c42537 --- /dev/null +++ b/spring-activiti/src/main/resources/templates/homepage.html @@ -0,0 +1,6 @@ + + + +

Home page

+ + \ No newline at end of file diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index 787aa87459..d4ea7bd306 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -35,6 +35,7 @@ org.springframework spring-oxm + ${spring-oxm.version} commons-logging @@ -69,8 +70,13 @@ com.h2database h2 + + org.springframework.batch + spring-batch-core + ${spring-batch-core.version} +
- + 5.8 4.0.0 @@ -78,6 +84,8 @@ 2.16.0 4.5.14 1.5.3 + 6.1.4 + 5.1.1 com.baeldung.batchtesting.SpringBatchApplication 3.2.2 5.10.2 diff --git a/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java b/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java index 311bd828cb..9822d10828 100644 --- a/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java +++ b/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java @@ -3,12 +3,15 @@ package com.baeldung.batchtesting; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.batch.test.AssertFile.assertFileEquals; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.List; -import com.baeldung.batchtesting.model.Book; -import com.baeldung.batchtesting.model.BookRecord; - import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; @@ -25,13 +28,15 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.core.io.FileSystemResource; import org.springframework.test.context.ContextConfiguration; +import com.baeldung.batchtesting.model.Book; +import com.baeldung.batchtesting.model.BookRecord; @SpringBatchTest @EnableAutoConfiguration @ContextConfiguration(classes = { SpringBatchConfiguration.class }) public class SpringBatchStepScopeIntegrationTest { - private static final String TEST_OUTPUT = "src/test/resources/output/actual-output.json"; + private static String TEST_OUTPUT = "src/test/resources/output/actual-output.json"; private static final String EXPECTED_OUTPUT_ONE = "src/test/resources/output/expected-output-one.json"; @@ -45,6 +50,13 @@ public class SpringBatchStepScopeIntegrationTest { @Autowired private JobRepositoryTestUtils jobRepositoryTestUtils; + @BeforeAll + public static void setup() throws IOException { + final File tempFile = Files.createTempFile("actual-output", ".json").toFile(); + Files.copy(Paths.get(TEST_OUTPUT), Paths.get(tempFile.getAbsolutePath()), StandardCopyOption.REPLACE_EXISTING); + TEST_OUTPUT = tempFile.getAbsolutePath(); + } + private JobParameters defaultJobParameters() { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); paramsBuilder.addString("file.input", TEST_INPUT_ONE); diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 221c3876d4..bb1af47126 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -20,22 +20,24 @@ spring-boot-admin spring-boot-angular spring-boot-annotations - + spring-boot-annotations-2 spring-boot-artifacts spring-boot-artifacts-2 spring-boot-autoconfiguration spring-boot-basic-customization spring-boot-basic-customization-2 spring-boot-bootstrap + spring-boot-caching + spring-boot-caching-2 spring-boot-client spring-boot-config-jpa-error spring-boot-ctx-fluent spring-boot-deployment - + spring-boot-di spring-boot-disable-logging spring-boot-ci-cd - + spring-boot-custom-starter spring-boot-crud spring-boot-data spring-boot-environment @@ -45,7 +47,7 @@ spring-boot-jasypt - + spring-boot-jsp spring-boot-keycloak spring-boot-keycloak-2 @@ -54,11 +56,11 @@ spring-boot-process-automation spring-boot-logging-logback spring-boot-logging-log4j2 - + spring-boot-mvc spring-boot-mvc-2 spring-boot-mvc-3 spring-boot-mvc-4 - + spring-boot-mvc-5 spring-boot-mvc-birt spring-boot-mvc-jersey spring-boot-nashorn @@ -66,45 +68,44 @@ spring-boot-performance spring-boot-property-exp spring-boot-request-params - - + spring-boot-runtime + spring-boot-runtime-2 spring-boot-security spring-boot-security-2 spring-boot-ssl-bundles spring-boot-telegram - - + spring-boot-springdoc + spring-boot-swagger spring-boot-swagger-jwt spring-boot-swagger-keycloak spring-boot-swagger-springfox - - + spring-boot-testing + spring-boot-testing-2 spring-boot-testing-spock spring-boot-vue spring-boot-actuator spring-boot-data-2 spring-boot-validation - - - + spring-boot-redis spring-boot-cassandre - + spring-boot-react + spring-caching-3 spring-boot-3-grpc - + spring-boot-3-native spring-boot-3-observation spring-boot-3-test-pitfalls spring-boot-3-testcontainers - + spring-boot-3-2 spring-boot-resilience4j spring-boot-properties spring-boot-properties-2 - + spring-boot-properties-3 spring-boot-properties-4 spring-boot-properties-migrator-demo - spring-boot-aws + spring-boot-aws spring-boot-keycloak-adapters spring-boot-mvc-legacy spring-boot-springdoc-2 @@ -112,6 +113,8 @@ spring-boot-3-url-matching spring-boot-graalvm-docker spring-boot-validations + spring-boot-openapi + spring-boot-brave diff --git a/spring-boot-modules/spring-boot-3-2/pom.xml b/spring-boot-modules/spring-boot-3-2/pom.xml index 29ad9898fb..29d9332ca5 100644 --- a/spring-boot-modules/spring-boot-3-2/pom.xml +++ b/spring-boot-modules/spring-boot-3-2/pom.xml @@ -196,6 +196,11 @@ io.zipkin.reporter2 zipkin-sender-urlconnection
+ + io.swagger.core.v3 + swagger-core + 2.2.20 + @@ -290,7 +295,7 @@ com.baeldung.restclient.RestClientApplication 1.6.0.Beta1 - 2.0.0 + 2.3.0 3.0.0-M7 5.14.0 0.2.0 diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientLiveTest.java similarity index 95% rename from spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java rename to spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientLiveTest.java index 3e12215bcb..0284d780a9 100644 --- a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java +++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/restclient/RestClientLiveTest.java @@ -15,13 +15,15 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; import org.springframework.web.client.RestClient; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class RestClientIntegrationTest { +@TestPropertySource(locations="classpath:connectiondetails/application-r2dbc.properties") +public class RestClientLiveTest { @LocalServerPort private int port; @@ -110,7 +112,7 @@ public class RestClientIntegrationTest { .uri(uriBase + "/articles/1234") .retrieve() .onStatus(status -> status.value() == 404, (request, response) -> { throw new ArticleNotFoundException(); }) - .body(new ParameterizedTypeReference<>() {}); + .body(new ParameterizedTypeReference() {}); }).isInstanceOf(ArticleNotFoundException.class); } diff --git a/spring-boot-modules/spring-boot-3/README.md b/spring-boot-modules/spring-boot-3/README.md index ff00a506cf..cc3ec77335 100644 --- a/spring-boot-modules/spring-boot-3/README.md +++ b/spring-boot-modules/spring-boot-3/README.md @@ -8,5 +8,5 @@ - [HTTP Interface in Spring 6](https://www.baeldung.com/spring-6-http-interface) - [Working with Virtual Threads in Spring 6](https://www.baeldung.com/spring-6-virtual-threads) - [Docker Compose Support in Spring Boot 3](https://www.baeldung.com/ops/docker-compose-support-spring-boot) - +- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring](https://www.baeldung.com/spring-5-junit-config) - More articles: [[next -->]](/spring-boot-modules/spring-boot-3-2) diff --git a/spring-boot-modules/spring-boot-annotations-2/pom.xml b/spring-boot-modules/spring-boot-annotations-2/pom.xml index 71fc7ff388..b7522772aa 100644 --- a/spring-boot-modules/spring-boot-annotations-2/pom.xml +++ b/spring-boot-modules/spring-boot-annotations-2/pom.xml @@ -26,6 +26,7 @@ org.mockito mockito-inline + ${mockito-inline.version} test @@ -33,6 +34,15 @@ spring-boot-starter-test test + + org.apache.commons + commons-lang3 + + + 5.2.0 + com.baeldung.springbootconfiguration.Application + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java index 7294d843d1..facafb13c2 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java @@ -9,12 +9,12 @@ public class ConditionalUtils { return SystemUtils.IS_OS_WINDOWS; } - public static boolean isJava8() { - return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT); + public static boolean isJava17() { + return JavaVersion.getJavaVersion().equals(JavaVersion.SEVENTEEN); } - public static boolean isJava9() { - return JavaVersion.getJavaVersion().equals(JavaVersion.NINE); + public static boolean isJava21() { + return JavaVersion.getJavaVersion().equals(JavaVersion.TWENTY_ONE); } } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17Condition.java similarity index 77% rename from spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17Condition.java index c5f5e16d52..cdf6cfde58 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17Condition.java @@ -4,10 +4,10 @@ import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; -public class Java8Condition implements Condition { +public class Java17Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - return ConditionalUtils.isJava8(); + return ConditionalUtils.isJava17(); } } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17DependedService.java similarity index 69% rename from spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17DependedService.java index ab76dcd930..2cf3dea8ec 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17DependedService.java @@ -4,6 +4,6 @@ import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Service; @Service -@Conditional(Java8Condition.class) -public class Java8DependedService { +@Conditional(Java17Condition.class) +public class Java17DependedService { } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17OrJava21.java similarity index 52% rename from spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17OrJava21.java index 77c501ed08..fdc5f866bc 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java17OrJava21.java @@ -3,14 +3,14 @@ package com.baeldung.annotations.conditional; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.context.annotation.Conditional; -public class Java8OrJava9 extends AnyNestedCondition { - Java8OrJava9() { +public class Java17OrJava21 extends AnyNestedCondition { + Java17OrJava21() { super(ConfigurationPhase.REGISTER_BEAN); } - @Conditional(Java8Condition.class) - static class Java8 { } + @Conditional(Java17Condition.class) + static class Java17 { } - @Conditional(Java9Condition.class) - static class Java9 { } + @Conditional(Java21Condition.class) + static class Java21 { } } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java21Condition.java similarity index 77% rename from spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java21Condition.java index 2afa8b25a7..ec0f3a499e 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java21Condition.java @@ -4,10 +4,10 @@ import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; -public class Java9Condition implements Condition { +public class Java21Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - return ConditionalUtils.isJava9(); + return ConditionalUtils.isJava21(); } } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java index e104ec86e1..fa619acdb7 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java @@ -8,12 +8,12 @@ import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Service; @Service -@Conditional({IsDevEnvCondition.class, IsWindowsCondition.class, Java8Condition.class}) +@Conditional({IsDevEnvCondition.class, IsWindowsCondition.class, Java17Condition.class}) @ConditionalOnProperty( value = "logging.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnExpression("${logging.enabled:true} and '${logging.level}'.equals('DEBUG')") -@ConditionalOnJava(JavaVersion.EIGHT) +@ConditionalOnJava(JavaVersion.SEVENTEEN) public class LoggingService { } diff --git a/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java17ConditionUnitTest.java similarity index 71% rename from spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java17ConditionUnitTest.java index ce277e81fe..560cd5537d 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java17ConditionUnitTest.java @@ -7,15 +7,15 @@ import org.mockito.Mockito; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; -public class Java9ConditionUnitTest { +public class Java17ConditionUnitTest { @Test - public void whenOnJava9_thenJava9ConditionShouldPass() { + public void whenOnJava17_thenJava7ConditionShouldPass() { try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { - theMock.when(ConditionalUtils::isJava9) + theMock.when(ConditionalUtils::isJava17) .thenReturn(true); Assertions.assertTrue( - new Java9Condition().matches( + new Java17Condition().matches( Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) ) ); @@ -24,12 +24,12 @@ public class Java9ConditionUnitTest { } @Test - public void whenNotOnJava9_thenJava9ConditionShouldNotPass() { + public void whenNotOnJava17_thenJava17ConditionShouldNotPass() { try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { - theMock.when(ConditionalUtils::isJava9) + theMock.when(ConditionalUtils::isJava17) .thenReturn(false); Assertions.assertFalse( - new Java9Condition().matches( + new Java17Condition().matches( Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) ) ); diff --git a/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java21ConditionUnitTest.java similarity index 72% rename from spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java21ConditionUnitTest.java index 0d1b1eded6..397f95c16c 100644 --- a/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java +++ b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java21ConditionUnitTest.java @@ -7,15 +7,15 @@ import org.mockito.Mockito; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; -public class Java8ConditionUnitTest { +public class Java21ConditionUnitTest { @Test - public void whenOnJava8_thenJava8ConditionShouldPass() { + public void whenOnJava21_thenJava21ConditionShouldPass() { try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { - theMock.when(ConditionalUtils::isJava8) + theMock.when(ConditionalUtils::isJava21) .thenReturn(true); Assertions.assertTrue( - new Java8Condition().matches( + new Java21Condition().matches( Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) ) ); @@ -24,12 +24,12 @@ public class Java8ConditionUnitTest { } @Test - public void whenNotOnJava8_thenJava8ConditionShouldNotPass() { + public void whenNotOnJava21_thenJava21ConditionShouldNotPass() { try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { - theMock.when(ConditionalUtils::isJava8) + theMock.when(ConditionalUtils::isJava21) .thenReturn(false); Assertions.assertFalse( - new Java8Condition().matches( + new Java21Condition().matches( Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) ) ); diff --git a/spring-boot-modules/spring-boot-artifacts/pom.xml b/spring-boot-modules/spring-boot-artifacts/pom.xml index e39ddb5af1..e0e745f72c 100644 --- a/spring-boot-modules/spring-boot-artifacts/pom.xml +++ b/spring-boot-modules/spring-boot-artifacts/pom.xml @@ -51,11 +51,6 @@ javax.persistence-api ${jpa.version}
- - com.google.guava - guava - ${guava.version} - org.subethamail subethasmtp diff --git a/spring-boot-modules/spring-boot-aws/pom.xml b/spring-boot-modules/spring-boot-aws/pom.xml index 44cd38be3f..8be0b230cd 100644 --- a/spring-boot-modules/spring-boot-aws/pom.xml +++ b/spring-boot-modules/spring-boot-aws/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.11 + 3.1.5 @@ -24,8 +24,21 @@ com.amazonaws.serverless - aws-serverless-java-container-springboot2 - ${aws-serverless-java-container-springboot2.version} + aws-serverless-java-container-springboot3 + ${aws-serverless-java-container.version} + + + com.amazonaws.serverless + aws-serverless-java-container-core + ${aws-serverless-java-container.version} + tests + test-jar + test + + + org.apache.httpcomponents.client5 + httpclient5 + ${httpclient5.version} org.springframework.boot @@ -74,10 +87,11 @@ - 1.9.1 - 3.2.4 + 2.0.0 + 3.3.0 11 11 + 5.3.1 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-3/README.md b/spring-boot-modules/spring-boot-basic-customization-3/README.md new file mode 100644 index 0000000000..0c12a370f9 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/README.md @@ -0,0 +1,6 @@ +## Spring Boot Basic Customization 3 + +This module contains articles about Spring Boot customization 3 + +### Relevant Articles: +- [How to Autowire a Spring Bean in a Servlet Filter](https://www.baeldung.com/spring-autowire-bean-servlet-filter) diff --git a/docker-modules/docker-compose/pom.xml b/spring-boot-modules/spring-boot-basic-customization-3/pom.xml similarity index 72% rename from docker-modules/docker-compose/pom.xml rename to spring-boot-modules/spring-boot-basic-customization-3/pom.xml index 90e0226c98..1b09162cf4 100644 --- a/docker-modules/docker-compose/pom.xml +++ b/spring-boot-modules/spring-boot-basic-customization-3/pom.xml @@ -1,10 +1,12 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - docker-compose - Demo project for Spring Boot and Docker + spring-boot-basic-customization-3 + spring-boot-basic-customization-3 + jar + Module For Spring Boot Basic Customization 3 com.baeldung @@ -14,18 +16,17 @@ - - org.springframework.boot - spring-boot-starter - org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-actuator + org.springframework.boot spring-boot-starter-test - test @@ -35,7 +36,8 @@ org.springframework.boot spring-boot-maven-plugin - com.baeldung.docker.app.DockAppApplication + springStartupApp + com.baeldung.springStart.SpringStartApplication diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java new file mode 100644 index 0000000000..f90c7b2889 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java @@ -0,0 +1,30 @@ +package com.baeldung.filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.DelegatingFilterProxy; + +@Configuration +public class AppConfig { + + @Bean + public FilterRegistrationBean loggingFilterDelegatingProxy() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new DelegatingFilterProxy("loggingFilterDelegateProxy")); + registrationBean.addUrlPatterns("/*"); + return registrationBean; + } + + @Bean + @Autowired + public FilterRegistrationBean loggingFilterRegistration(LoggingService loggingService) { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new LoggingFilterRegistrationBean(loggingService)); + registrationBean.addUrlPatterns("/*"); + return registrationBean; + } + + +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterAutowiringSupport.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterAutowiringSupport.java new file mode 100644 index 0000000000..6aaf521ee8 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterAutowiringSupport.java @@ -0,0 +1,35 @@ +package com.baeldung.filter; + +import java.io.IOException; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.SpringBeanAutowiringSupport; + +@Component +public class LoggingFilterAutowiringSupport implements Filter { + + @Autowired + LoggingService loggingService; + + @Override + public void init(FilterConfig filterConfig) { + SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, + filterConfig.getServletContext()); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + loggingService.log(httpServletRequest.getMethod(), httpServletRequest.getRequestURI()); + filterChain.doFilter(servletRequest, servletResponse); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxy.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxy.java new file mode 100644 index 0000000000..84f0477379 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxy.java @@ -0,0 +1,27 @@ +package com.baeldung.filter; + +import java.io.IOException; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.Filter; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("loggingFilterDelegateProxy") +public class LoggingFilterDelegatingFilterProxy implements Filter { + + @Autowired + LoggingService loggingService; + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + loggingService.log(httpServletRequest.getMethod(), httpServletRequest.getRequestURI()); + filterChain.doFilter(servletRequest, servletResponse); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterRegistrationBean.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterRegistrationBean.java new file mode 100644 index 0000000000..ec2c57c3a0 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterRegistrationBean.java @@ -0,0 +1,32 @@ +package com.baeldung.filter; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.SpringBeanAutowiringSupport; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +@Component +public class LoggingFilterRegistrationBean implements Filter { + + private LoggingService loggingService; + + public LoggingFilterRegistrationBean(LoggingService loggingService) { + this.loggingService = loggingService; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + loggingService.log(httpServletRequest.getMethod(), httpServletRequest.getRequestURI()); + filterChain.doFilter(servletRequest, servletResponse); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterWebApplicationContext.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterWebApplicationContext.java new file mode 100644 index 0000000000..85d83ebd9d --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingFilterWebApplicationContext.java @@ -0,0 +1,34 @@ +package com.baeldung.filter; + +import java.io.IOException; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +@Component +public class LoggingFilterWebApplicationContext implements Filter { + + private LoggingService loggingService; + + @Override + public void init(FilterConfig filterConfig) { + loggingService = WebApplicationContextUtils + .getRequiredWebApplicationContext(filterConfig.getServletContext()) + .getBean(LoggingService.class); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + loggingService.log(httpServletRequest.getMethod(), httpServletRequest.getRequestURI()); + filterChain.doFilter(servletRequest, servletResponse); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingService.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingService.java new file mode 100644 index 0000000000..aaaa93a10b --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/LoggingService.java @@ -0,0 +1,14 @@ +package com.baeldung.filter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class LoggingService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + public void log(String message,String url){ + logger.info("Logging Request {} for URI : {}",message,url); + } +} diff --git a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/SpringBootFilterStartApp.java similarity index 59% rename from docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java rename to spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/SpringBootFilterStartApp.java index e7ff52015c..d497bc55ab 100644 --- a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/SpringBootFilterStartApp.java @@ -1,13 +1,12 @@ -package com.baeldung.docker.app; +package com.baeldung.filter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class DockAppApplication { +public class SpringBootFilterStartApp { public static void main(String[] args) { - SpringApplication.run(DockAppApplication.class, args); + SpringApplication.run(SpringBootFilterStartApp.class, args); } - } diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/User.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/User.java new file mode 100644 index 0000000000..983228e8c6 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/User.java @@ -0,0 +1,39 @@ +package com.baeldung.filter; + +public class User { + + private String id; + private String name; + private String email; + + public User(String id, String name, String email) { + this.id = id; + this.name = name; + this.email = email; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/UserController.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/UserController.java new file mode 100644 index 0000000000..a7e3daa749 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/UserController.java @@ -0,0 +1,17 @@ +package com.baeldung.filter; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class UserController { + + @GetMapping("/users") + public List getUsers(){ + return Arrays.asList(new User("1","John","john@email.com"), + new User("2","Smith","smith@email.com")); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/springStart/SpringStartApplication.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/springStart/SpringStartApplication.java new file mode 100644 index 0000000000..6648fd8498 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/springStart/SpringStartApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.springStart; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringStartApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringStartApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/resources/application.properties b/spring-boot-modules/spring-boot-basic-customization-3/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterAutowiringSupportUnitTest.java b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterAutowiringSupportUnitTest.java new file mode 100644 index 0000000000..785bd9c514 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterAutowiringSupportUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.filter; + +import java.lang.reflect.Field; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class LoggingFilterAutowiringSupportUnitTest { + + @Autowired + private LoggingFilterAutowiringSupport loggingFilter; + + @Test + public void givenFilter_whenAutowired_thenDependencyInjected() throws Exception { + Assert.assertNotNull(loggingFilter); + Assert.assertNotNull(getField(loggingFilter,"loggingService")); + } + + private Object getField(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(target); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxyUnitTest.java b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxyUnitTest.java new file mode 100644 index 0000000000..7d36a6fe10 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterDelegatingFilterProxyUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.filter; + +import java.lang.reflect.Field; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class LoggingFilterDelegatingFilterProxyUnitTest { + + @Autowired + private LoggingFilterDelegatingFilterProxy loggingFilter; + + @Test + public void testLoggingFilter() throws Exception { + Assert.assertNotNull(loggingFilter); + Assert.assertNotNull(getField(loggingFilter,"loggingService")); + } + + private Object getField(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(target); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterRegistrationBeanUnitTest.java b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterRegistrationBeanUnitTest.java new file mode 100644 index 0000000000..25f1714845 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/filter/LoggingFilterRegistrationBeanUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.filter; + +import java.lang.reflect.Field; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class LoggingFilterRegistrationBeanUnitTest { + + @Autowired + private LoggingFilterRegistrationBean loggingFilter; + + @Test + public void testLoggingFilter() throws Exception { + Assert.assertNotNull(loggingFilter); + Assert.assertNotNull(getField(loggingFilter,"loggingService")); + } + + private Object getField(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(target); + } +} diff --git a/spring-boot-modules/spring-boot-brave/pom.xml b/spring-boot-modules/spring-boot-brave/pom.xml new file mode 100644 index 0000000000..1cc8f44cf7 --- /dev/null +++ b/spring-boot-modules/spring-boot-brave/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + com.baeldung + spring-boot-brave + 1.0.0-SNAPSHOT + spring-boot-brave + jar + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + io.zipkin.brave + brave + 6.0.2 + + + io.zipkin.reporter2 + zipkin-reporter + 3.3.0 + + + io.zipkin.reporter2 + zipkin-sender-okhttp3 + 3.3.0 + + + io.zipkin.reporter2 + zipkin-reporter-brave + 3.3.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + \ No newline at end of file diff --git a/docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/Application.java similarity index 61% rename from docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java rename to spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/Application.java index b5e46f3eac..7c7bc05a07 100644 --- a/docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java +++ b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/Application.java @@ -1,13 +1,12 @@ -package com.baeldung.docker; +package com.baeldung.brave; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class MainApplication { +public class Application { public static void main(String[] args) { - SpringApplication.run(MainApplication .class, args); + SpringApplication.run(Application.class, args); } - } diff --git a/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/configuration/TracingConfiguration.java b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/configuration/TracingConfiguration.java new file mode 100644 index 0000000000..5b36fecce2 --- /dev/null +++ b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/configuration/TracingConfiguration.java @@ -0,0 +1,36 @@ +package com.baeldung.brave.configuration; + +import brave.Tracer; +import brave.Tracing; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import zipkin2.reporter.BytesMessageSender; +import zipkin2.reporter.brave.AsyncZipkinSpanHandler; +import zipkin2.reporter.okhttp3.OkHttpSender; + +@Configuration +public class TracingConfiguration { + + @Bean + BytesMessageSender sender() { + return OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans"); + } + + @Bean + AsyncZipkinSpanHandler zipkinSpanHandler(BytesMessageSender sender) { + return AsyncZipkinSpanHandler.create(sender); + } + + @Bean + public Tracing tracing(AsyncZipkinSpanHandler zipkinSpanHandler) { + return Tracing.newBuilder() + .localServiceName("Dummy Service") + .addSpanHandler(zipkinSpanHandler) + .build(); + } + + @Bean + public Tracer tracer(Tracing tracing) { + return tracing.tracer(); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/service/TracingService.java b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/service/TracingService.java new file mode 100644 index 0000000000..139718c54d --- /dev/null +++ b/spring-boot-modules/spring-boot-brave/src/main/java/com/baeldung/brave/service/TracingService.java @@ -0,0 +1,28 @@ +package com.baeldung.brave.service; + +import brave.Span; +import brave.Tracer; +import jakarta.annotation.PostConstruct; +import org.springframework.stereotype.Service; + +@Service +public class TracingService { + + private final Tracer tracer; + + public TracingService(Tracer tracer) { + this.tracer = tracer; + } + + @PostConstruct + private void postConstruct() { + Span span = tracer.nextSpan().name("Hello from Service").start(); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + span.finish(); + } + } +} diff --git a/spring-boot-modules/spring-caching-2/README.md b/spring-boot-modules/spring-boot-caching-2/README.md similarity index 67% rename from spring-boot-modules/spring-caching-2/README.md rename to spring-boot-modules/spring-boot-caching-2/README.md index 864a17d98b..a2b0c41c63 100644 --- a/spring-boot-modules/spring-caching-2/README.md +++ b/spring-boot-modules/spring-boot-caching-2/README.md @@ -2,4 +2,6 @@ - [Spring Boot Cache with Redis](https://www.baeldung.com/spring-boot-redis-cache) - [Setting Time-To-Live Value for Caching](https://www.baeldung.com/spring-setting-ttl-value-cache) - [Get All Cached Keys with Caffeine Cache in Spring Boot](https://www.baeldung.com/spring-boot-caffeine-spring-get-all-keys) +- [Implement Two-Level Cache With Spring](https://www.baeldung.com/spring-two-level-cache) +- More articles: [[<-- prev]](/spring-boot-modules/spring-boot-caching) diff --git a/spring-boot-modules/spring-caching-2/pom.xml b/spring-boot-modules/spring-boot-caching-2/pom.xml similarity index 95% rename from spring-boot-modules/spring-caching-2/pom.xml rename to spring-boot-modules/spring-boot-caching-2/pom.xml index ec9215aa32..95fae4a0ef 100644 --- a/spring-boot-modules/spring-caching-2/pom.xml +++ b/spring-boot-modules/spring-boot-caching-2/pom.xml @@ -51,7 +51,7 @@ ${caffeine.version} - it.ozimov + com.github.codemonstur embedded-redis ${embedded.redis.version} @@ -65,7 +65,7 @@ - 0.7.3 + 1.4.0 3.1.8 com.baeldung.caching.ttl.CachingTTLApplication diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/Item.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/Item.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java new file mode 100644 index 0000000000..576bcd97ab --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -0,0 +1,71 @@ +package com.baeldung.caching.twolevelcache; + +import com.github.benmanes.caffeine.cache.Caffeine; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.AnnotationCacheOperationSource; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.interceptor.CacheInterceptor; +import org.springframework.cache.interceptor.CacheOperationSource; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; + +import java.time.Duration; +import java.util.Arrays; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + @Primary + public CacheManager caffeineCacheManager(CaffeineCache caffeineCache) { + SimpleCacheManager manager = new SimpleCacheManager(); + manager.setCaches(Arrays.asList(caffeineCache)); + return manager; + } + + @Bean + public CaffeineCache caffeineCacheConfig() { + return new CaffeineCache("customerCache", Caffeine.newBuilder() + .expireAfterWrite(Duration.ofSeconds(3)) + .initialCapacity(1) + .maximumSize(2000) + .build()); + } + + @Bean + public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory, RedisCacheConfiguration redisCacheConfiguration) { + return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory) + .withCacheConfiguration("customerCache", redisCacheConfiguration) + .build(); + } + + @Bean + public RedisCacheConfiguration cacheConfiguration() { + return RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(5)) + .disableCachingNullValues() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); + } + + @Bean + public CacheInterceptor cacheInterceptor(CacheManager caffeineCacheManager, CacheOperationSource cacheOperationSource) { + CacheInterceptor interceptor = new CustomerCacheInterceptor(caffeineCacheManager); + interceptor.setCacheOperationSources(cacheOperationSource); + return interceptor; + } + + @Bean + public CacheOperationSource cacheOperationSource() { + return new AnnotationCacheOperationSource(); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java new file mode 100644 index 0000000000..0b985d35f3 --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java @@ -0,0 +1,25 @@ +package com.baeldung.caching.twolevelcache; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +@Data +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Setter +public class Customer implements Serializable { + + @Id + private String id; + + private String name; + + private String email; +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java new file mode 100644 index 0000000000..f1a8dca0db --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java @@ -0,0 +1,29 @@ +package com.baeldung.caching.twolevelcache; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.interceptor.CacheInterceptor; +import org.springframework.data.redis.cache.RedisCache; + +public class CustomerCacheInterceptor extends CacheInterceptor { + + private final CacheManager caffeineCacheManager; + + public CustomerCacheInterceptor(CacheManager caffeineCacheManager) { + this.caffeineCacheManager = caffeineCacheManager; + } + + @Override + protected Cache.ValueWrapper doGet(Cache cache, Object key) { + Cache.ValueWrapper existingCacheValue = super.doGet(cache, key); + + if (existingCacheValue != null && cache.getClass() == RedisCache.class) { + Cache caffeineCache = caffeineCacheManager.getCache(cache.getName()); + if (caffeineCache != null) { + caffeineCache.putIfAbsent(key, existingCacheValue.get()); + } + } + + return existingCacheValue; + } +} diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java new file mode 100644 index 0000000000..098112f152 --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.caching.twolevelcache; + +import org.springframework.data.repository.CrudRepository; + +public interface CustomerRepository extends CrudRepository { +} diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java new file mode 100644 index 0000000000..088b66919c --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java @@ -0,0 +1,26 @@ +package com.baeldung.caching.twolevelcache; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; + +@Service +public class CustomerService { + + private final CustomerRepository customerRepository; + + @Autowired + public CustomerService(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + @Caching(cacheable = { + @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), + @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") + }) + public Customer getCustomer(String id) { + return customerRepository.findById(id) + .orElseThrow(RuntimeException::new); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java new file mode 100644 index 0000000000..9bc2c65e6e --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.caching.twolevelcache; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TwoLevelCacheApplication { + + public static void main(String[] args) { + SpringApplication.run(TwoLevelCacheApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-caching-2/src/main/resources/application.properties similarity index 89% rename from spring-boot-modules/spring-caching-2/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-caching-2/src/main/resources/application.properties index 38f3537d01..49bd715e43 100644 --- a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-caching-2/src/main/resources/application.properties @@ -11,3 +11,4 @@ caching.spring.hotelListTTL=43200 # Connection details #spring.redis.host=localhost #spring.redis.port=6379 +spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/data.sql b/spring-boot-modules/spring-boot-caching-2/src/main/resources/data.sql similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/resources/data.sql rename to spring-boot-modules/spring-boot-caching-2/src/main/resources/data.sql diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java similarity index 93% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 8868edb74f..01740ba780 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -5,8 +5,6 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import java.util.Optional; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,10 +18,12 @@ import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit.jupiter.SpringExtension; +import redis.embedded.RedisServer; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; -import redis.embedded.RedisServer; +import java.io.IOException; +import java.util.Optional; @Import({ CacheConfig.class, ItemService.class }) @ExtendWith(SpringExtension.class) @@ -69,17 +69,17 @@ class ItemServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() { + public EmbeddedRedisConfiguration() throws IOException { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() { + public void startRedis() throws IOException { redisServer.start(); } @PreDestroy - public void stopRedis() { + public void stopRedis() throws IOException { this.redisServer.stop(); } } diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java diff --git a/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java new file mode 100644 index 0000000000..3db53198fc --- /dev/null +++ b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -0,0 +1,124 @@ +package com.baeldung.caching.twolevelcache; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import redis.embedded.RedisServer; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import java.io.IOException; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +@Import({ CacheConfig.class,CustomerService.class }) +@ExtendWith(SpringExtension.class) +@ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) +@EnableCaching +class CustomerServiceCachingIntegrationTest { + + @MockBean + private CustomerRepository customerRepository; + + @Autowired + private CustomerService customerService; + + @Autowired + private CacheManager redisCacheManager; + + @Autowired + private CacheManager caffeineCacheManager; + + @Test + void givenCustomerIsPresent_whenGetCustomerCalled_thenReturnCustomerAndCacheIt() { + String CUSTOMER_ID = "100"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); + + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); + + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); + + assertThat(customerCacheMiss).isEqualTo(customer); + verify(customerRepository, times(1)).findById(CUSTOMER_ID); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + } + + @Test + void givenCustomerIsPresent_whenGetCustomerCalledTwice_thenReturnCustomerAndCacheIt() { + String CUSTOMER_ID = "101"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); + + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); + Customer customerCacheHit = customerService.getCustomer(CUSTOMER_ID); + + assertThat(customerCacheMiss).isEqualTo(customer); + assertThat(customerCacheHit).isEqualTo(customer); + verify(customerRepository, times(1)).findById(CUSTOMER_ID); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + } + + @Test + void givenCustomerIsPresent_whenGetCustomerCalledTwiceAndFirstCacheExpired_thenReturnCustomerAndCacheIt() throws InterruptedException { + String CUSTOMER_ID = "102"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); + + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); + TimeUnit.SECONDS.sleep(3); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(null); + Customer customerCacheHit = customerService.getCustomer(CUSTOMER_ID); + + verify(customerRepository, times(1)).findById(CUSTOMER_ID); + assertThat(customerCacheMiss).isEqualTo(customer); + assertThat(customerCacheHit).isEqualTo(customer); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + } + + private Object customerFromRedisCache(String key) { + return redisCacheManager.getCache("customerCache").get(key) != null ? + redisCacheManager.getCache("customerCache").get(key).get() : null; + } + + private Object customerFromCaffeineCache(String key) { + return caffeineCacheManager.getCache("customerCache").get(key) != null ? + caffeineCacheManager.getCache("customerCache").get(key).get() : null; + } + + @TestConfiguration + static class EmbeddedRedisConfiguration { + + private final RedisServer redisServer; + + public EmbeddedRedisConfiguration() throws IOException { + this.redisServer = new RedisServer(); + } + + @PostConstruct + public void startRedis() throws IOException { + redisServer.start(); + } + + @PreDestroy + public void stopRedis() throws IOException { + this.redisServer.stop(); + } + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/test/resources/application.properties b/spring-boot-modules/spring-boot-caching-2/src/test/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/resources/application.properties rename to spring-boot-modules/spring-boot-caching-2/src/test/resources/application.properties diff --git a/spring-boot-modules/spring-caching/README.md b/spring-boot-modules/spring-boot-caching/README.md similarity index 89% rename from spring-boot-modules/spring-caching/README.md rename to spring-boot-modules/spring-boot-caching/README.md index e10d6080e8..1690be8f47 100644 --- a/spring-boot-modules/spring-caching/README.md +++ b/spring-boot-modules/spring-boot-caching/README.md @@ -6,3 +6,4 @@ - [Using Multiple Cache Managers in Spring](https://www.baeldung.com/spring-multiple-cache-managers) - [Testing @Cacheable on Spring Data Repositories](https://www.baeldung.com/spring-data-testing-cacheable) - [Spring Boot Ehcache Example](https://www.baeldung.com/spring-boot-ehcache) +- More articles: [[next -->]](/spring-boot-modules/spring-boot-caching-2) \ No newline at end of file diff --git a/spring-boot-modules/spring-caching/pom.xml b/spring-boot-modules/spring-boot-caching/pom.xml similarity index 92% rename from spring-boot-modules/spring-caching/pom.xml rename to spring-boot-modules/spring-boot-caching/pom.xml index 5b4dde6e8b..36fbe6ef27 100644 --- a/spring-boot-modules/spring-caching/pom.xml +++ b/spring-boot-modules/spring-boot-caching/pom.xml @@ -9,10 +9,9 @@ war - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT @@ -49,7 +48,6 @@ com.github.ben-manes.caffeine caffeine - ${caffeine.version} com.h2database diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/Application.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/Application.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/Application.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/Application.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/AbstractService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/AbstractService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/AbstractService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/AbstractService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/BookService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/BookService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/BookService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/BookService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/Customer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/Customer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/Customer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/Customer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/model/Book.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/model/Book.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/model/Book.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/model/Book.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/resources/application.properties b/spring-boot-modules/spring-boot-caching/src/main/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-caching/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-caching/src/main/resources/config.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/config.xml similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/config.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/config.xml diff --git a/spring-boot-modules/spring-caching/src/main/resources/data.sql b/spring-boot-modules/spring-boot-caching/src/main/resources/data.sql similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/data.sql rename to spring-boot-modules/spring-boot-caching/src/main/resources/data.sql diff --git a/spring-boot-modules/spring-caching/src/main/resources/ehcache.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/ehcache.xml similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/ehcache.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/ehcache.xml diff --git a/dozer/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/logback.xml similarity index 100% rename from dozer/src/main/resources/logback.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/logback.xml diff --git a/spring-boot-modules/spring-caching/src/main/resources/schema.sql b/spring-boot-modules/spring-boot-caching/src/main/resources/schema.sql similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/schema.sql rename to spring-boot-modules/spring-boot-caching/src/main/resources/schema.sql diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-ci-cd/pom.xml b/spring-boot-modules/spring-boot-ci-cd/pom.xml index 6e58f1162d..51adb6bc1b 100644 --- a/spring-boot-modules/spring-boot-ci-cd/pom.xml +++ b/spring-boot-modules/spring-boot-ci-cd/pom.xml @@ -105,7 +105,7 @@ - 0.8.5 + 0.8.11 3.0.2 2.2.0 diff --git a/spring-boot-modules/spring-boot-client/pom.xml b/spring-boot-modules/spring-boot-client/pom.xml index bbdc6cca7d..13fb780e45 100644 --- a/spring-boot-modules/spring-boot-client/pom.xml +++ b/spring-boot-modules/spring-boot-client/pom.xml @@ -33,11 +33,7 @@ org.springframework.boot spring-boot-starter - - com.google.guava - guava - ${guava.version} - + org.springframework spring-websocket diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/sample/GreeterSampleApplication.java b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/GreeterSampleApplication.java similarity index 94% rename from spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/sample/GreeterSampleApplication.java rename to spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/GreeterSampleApplication.java index 5aa3ac7015..f573179c29 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/sample/GreeterSampleApplication.java +++ b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/main/java/com/baeldung/greeter/GreeterSampleApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.greeter.sample; +package com.baeldung.greeter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; @@ -6,7 +6,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.baeldung.greeter.library.Greeter; - @SpringBootApplication public class GreeterSampleApplication implements CommandLineRunner { diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/SpringContextTest.java index 7103da97f3..e446dddc69 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/SpringContextTest.java @@ -5,7 +5,7 @@ import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.greeter.sample.GreeterSampleApplication; +import com.baeldung.greeter.GreeterSampleApplication; @RunWith(SpringRunner.class) @SpringBootTest(classes = GreeterSampleApplication.class) diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/sample/GreeterSampleApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/GreeterSampleApplicationIntegrationTest.java similarity index 97% rename from spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/sample/GreeterSampleApplicationIntegrationTest.java rename to spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/GreeterSampleApplicationIntegrationTest.java index 50193ccd60..e53be5fafd 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/sample/GreeterSampleApplicationIntegrationTest.java +++ b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/src/test/java/com/baeldung/greeter/GreeterSampleApplicationIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.greeter.sample; +package com.baeldung.greeter; import static org.junit.Assert.assertEquals; diff --git a/spring-boot-modules/spring-boot-custom-starter/pom.xml b/spring-boot-modules/spring-boot-custom-starter/pom.xml index aee98b125e..d18aabac19 100644 --- a/spring-boot-modules/spring-boot-custom-starter/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/pom.xml @@ -23,4 +23,9 @@ parent-multi-module + + true + 3.2.2 + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-3/README.md b/spring-boot-modules/spring-boot-data-3/README.md index 94516a506c..da50d52bc2 100644 --- a/spring-boot-modules/spring-boot-data-3/README.md +++ b/spring-boot-modules/spring-boot-data-3/README.md @@ -3,3 +3,4 @@ - [Integrate AWS Secrets Manager in Spring Boot](https://www.baeldung.com/spring-boot-integrate-aws-secrets-manager) - [Fix Spring Data JPA Exception: No Property Found for Type](https://www.baeldung.com/spring-data-jpa-exception-no-property-found-for-type) - [Remove Null Objects in JSON Response When Using Spring and Jackson](https://www.baeldung.com/spring-remove-null-objects-json-response-jackson) +- [Skip Select Before Insert in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-skip-select-insert) diff --git a/spring-boot-modules/spring-boot-data-3/pom.xml b/spring-boot-modules/spring-boot-data-3/pom.xml index 726a6e70eb..0d35da3a0a 100644 --- a/spring-boot-modules/spring-boot-data-3/pom.xml +++ b/spring-boot-modules/spring-boot-data-3/pom.xml @@ -10,16 +10,17 @@ spring-boot-data-3 - com.baeldung.spring-boot-modules - spring-boot-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 io.hypersistence - hypersistence-utils-hibernate-55 - 3.7.1 + hypersistence-utils-hibernate-60 + ${hypersistence-utils-hibernate-60.version} org.springframework.boot @@ -68,6 +69,7 @@ 2.4.4 1.0.11 com.baeldung.startwithoutdb.StartWithoutDbApplication + 3.7.3 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/PersistableTask.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/PersistableTask.java index 949aa2935d..119789dcd8 100644 --- a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/PersistableTask.java +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/PersistableTask.java @@ -1,8 +1,8 @@ package com.baeldung.skipselectbeforeinsert.model; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; import org.springframework.data.domain.Persistable; diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/Task.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/Task.java index 9b8eaa8f6b..caeb2a9ab6 100644 --- a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/Task.java +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/Task.java @@ -1,9 +1,9 @@ package com.baeldung.skipselectbeforeinsert.model; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; @Entity public class Task { diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/TaskWithGeneratedId.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/TaskWithGeneratedId.java index a3ea2a8ad0..cff4cc452f 100644 --- a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/TaskWithGeneratedId.java +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/model/TaskWithGeneratedId.java @@ -1,9 +1,9 @@ package com.baeldung.skipselectbeforeinsert.model; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; @Entity public class TaskWithGeneratedId { diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/repository/TaskRepositoryExtensionImpl.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/repository/TaskRepositoryExtensionImpl.java index 86ff10a521..131a8ca50c 100644 --- a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/repository/TaskRepositoryExtensionImpl.java +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/skipselectbeforeinsert/repository/TaskRepositoryExtensionImpl.java @@ -1,7 +1,7 @@ package com.baeldung.skipselectbeforeinsert.repository; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import org.springframework.stereotype.Component; diff --git a/spring-boot-modules/spring-boot-data/pom.xml b/spring-boot-modules/spring-boot-data/pom.xml index 5c76035a3a..b0dffa3f6d 100644 --- a/spring-boot-modules/spring-boot-data/pom.xml +++ b/spring-boot-modules/spring-boot-data/pom.xml @@ -157,6 +157,8 @@ + 3.2.2 + 5.10.2 2.2.4 19 com.baeldung.SpringBootDataApplication diff --git a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties index cee5701cb5..7ad6ca058f 100644 --- a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties @@ -6,5 +6,6 @@ spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password= +spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java index cb2aee8cdf..435b12b000 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -44,7 +44,7 @@ public class ContactAppIntegrationTest { public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -59,7 +59,7 @@ public class ContactAppIntegrationTest { public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/javaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -74,7 +74,7 @@ public class ContactAppIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plainWithJavaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -89,7 +89,7 @@ public class ContactAppIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plain", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java index c5c57c2973..dfe1ba3baf 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -38,7 +38,7 @@ public class ContactAppWithObjectMapperCustomizerIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plainWithJavaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -53,7 +53,7 @@ public class ContactAppWithObjectMapperCustomizerIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plain", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); diff --git a/spring-boot-modules/spring-boot-deployment/pom.xml b/spring-boot-modules/spring-boot-deployment/pom.xml index 890a5be58f..2af3a4718e 100644 --- a/spring-boot-modules/spring-boot-deployment/pom.xml +++ b/spring-boot-modules/spring-boot-deployment/pom.xml @@ -56,11 +56,7 @@ javax.persistence-api ${jpa.version} - - com.google.guava - guava - ${guava.version} - + org.subethamail subethasmtp diff --git a/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java b/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java index f08a755fc7..4e157e4e13 100644 --- a/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java +++ b/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java @@ -13,10 +13,10 @@ 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.actuate.beans.BeansEndpoint.ContextBeansDescriptor; 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.boot.test.web.server.LocalServerPort; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -54,12 +54,12 @@ public class DisplayBeanIntegrationTest { @Test public void givenRestTemplate_whenAccessEndpointUrl_thenHttpStatusOK() throws Exception { - ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { + 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); + ResponseEntity> entity = this.testRestTemplate.exchange(requestEntity, responseType); then(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } diff --git a/spring-boot-modules/spring-boot-documentation/pom.xml b/spring-boot-modules/spring-boot-documentation/pom.xml index a941ca36e6..cb50ebe40f 100644 --- a/spring-boot-modules/spring-boot-documentation/pom.xml +++ b/spring-boot-modules/spring-boot-documentation/pom.xml @@ -18,20 +18,6 @@ - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - org.springframework.boot spring-boot-starter diff --git a/spring-boot-modules/spring-boot-environment/pom.xml b/spring-boot-modules/spring-boot-environment/pom.xml index 616a1c19cc..097c3c2175 100644 --- a/spring-boot-modules/spring-boot-environment/pom.xml +++ b/spring-boot-modules/spring-boot-environment/pom.xml @@ -46,11 +46,7 @@ h2 runtime - - com.google.guava - guava - ${guava.version} - + org.subethamail subethasmtp diff --git a/spring-boot-modules/spring-boot-graphql/README.md b/spring-boot-modules/spring-boot-graphql/README.md index 5f78461ce1..f71cc35b6d 100644 --- a/spring-boot-modules/spring-boot-graphql/README.md +++ b/spring-boot-modules/spring-boot-graphql/README.md @@ -13,6 +13,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [How to Test GraphQL Using Postman](https://www.baeldung.com/graphql-postman) - [GraphQL vs REST](https://www.baeldung.com/graphql-vs-rest) - [REST vs. GraphQL vs. gRPC – Which API to Choose?](https://www.baeldung.com/rest-vs-graphql-vs-grpc) +- [Implementing GraphQL Mutation Without Returning Data](https://www.baeldung.com/java-graphql-mutation-no-return-data) ### GraphQL sample queries diff --git a/spring-boot-modules/spring-boot-jsp/pom.xml b/spring-boot-modules/spring-boot-jsp/pom.xml index f4230a12f1..717267cfd3 100644 --- a/spring-boot-modules/spring-boot-jsp/pom.xml +++ b/spring-boot-modules/spring-boot-jsp/pom.xml @@ -55,6 +55,7 @@ org.springframework.boot spring-boot-devtools + org.projectlombok lombok @@ -101,8 +102,9 @@ 1.2 - 2.4.4 + 3.2.2 1.10.0 + 5.10.2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java index 1349ff5918..9975b2ff93 100644 --- a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.stream.Collectors; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -56,6 +57,9 @@ class SecurityConfig { @Bean public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth + // Allows preflight requests from browser + .requestMatchers(new AntPathRequestMatcher("/customers*", HttpMethod.OPTIONS.name())) + .permitAll() .requestMatchers(new AntPathRequestMatcher("/customers*")) .hasRole("user") .requestMatchers(new AntPathRequestMatcher("/")) diff --git a/spring-boot-modules/spring-boot-libraries-3/pom.xml b/spring-boot-modules/spring-boot-libraries-3/pom.xml index d0c1d345c0..e88ae4c078 100644 --- a/spring-boot-modules/spring-boot-libraries-3/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-3/pom.xml @@ -6,9 +6,10 @@ spring-boot-libraries-3 - spring-boot-modules - com.baeldung.spring-boot-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -19,31 +20,36 @@ org.springframework.kafka spring-kafka - ${spring-kafka.version} + + + + org.postgresql + postgresql + ${postgresql.version} org.springframework.modulith spring-modulith-events-api - ${spring-modulith-events-kafka.version} + ${spring-modulith.version} org.springframework.modulith spring-modulith-events-kafka - ${spring-modulith-events-kafka.version} + ${spring-modulith.version} - com.fasterxml.jackson.core - jackson-databind + org.springframework.modulith + spring-modulith-starter-jpa + ${spring-modulith.version} - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations + org.springframework.modulith + spring-modulith-starter-test + ${spring-modulith.version} + test + org.springframework.boot spring-boot-starter-test @@ -54,7 +60,6 @@ spring-boot-testcontainers test - org.testcontainers kafka @@ -73,10 +78,11 @@ ${testcontainers.version} test - - com.h2database - h2 + org.testcontainers + postgresql + ${testcontainers.version} + test @@ -85,15 +91,24 @@ ${awaitility.version} test + + com.h2database + h2 + ${h2.version} + test + 17 - 1.1.3 - 1.19.6 + 3.1.5 + 1.1.3 + 1.19.3 4.2.0 - 3.1.2 + 42.3.1 + 2.2.224 - \ No newline at end of file + + diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java new file mode 100644 index 0000000000..c448bd44dd --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java @@ -0,0 +1,12 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.time.Instant; +import java.util.List; + +record Order(String id, String customerId, List productIds, Instant timestamp) { + + public Order(String customerId, List productIds) { + this(null, customerId, productIds, Instant.now()); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java new file mode 100644 index 0000000000..4344b336ac --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java @@ -0,0 +1,6 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.time.Instant; + +public record OrderCompletedEvent(String orderId, String customerId, Instant timestamp) { +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java new file mode 100644 index 0000000000..7c159e3582 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +@Component +class OrderRepository { + private final List orders = new ArrayList<>(); + + public Order save(Order order) { + order = new Order(UUID.randomUUID() + .toString(), order.customerId(), order.productIds(), order.timestamp()); + orders.add(order); + return order; + } + + public List ordersByCustomer(String customerId) { + return orders.stream() + .filter(it -> it.customerId() + .equals(customerId)) + .toList(); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java new file mode 100644 index 0000000000..c60792813c --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java @@ -0,0 +1,29 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.util.Arrays; + +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +@Service +public class OrderService { + + private final OrderRepository repository; + private final ApplicationEventPublisher eventPublisher; + + public OrderService(OrderRepository orders, ApplicationEventPublisher eventsPublisher) { + this.repository = orders; + this.eventPublisher = eventsPublisher; + } + + public void placeOrder(String customerId, String... productIds) { + Order order = new Order(customerId, Arrays.asList(productIds)); + // business logic to validate and place the order + + Order savedOrder = repository.save(order); + + OrderCompletedEvent event = new OrderCompletedEvent(savedOrder.id(), savedOrder.customerId(), savedOrder.timestamp()); + eventPublisher.publishEvent(event); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java new file mode 100644 index 0000000000..29ba6fa8e2 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java @@ -0,0 +1,44 @@ +package com.baeldung.springmodulith.application.events.rewards; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.springframework.stereotype.Component; + +@Component +public class LoyalCustomersRepository { + + private List customers = new ArrayList<>(); + + public Optional find(String customerId) { + return customers.stream() + .filter(it -> it.customerId() + .equals(customerId)) + .findFirst(); + } + + public void awardPoints(String customerId, int points) { + var customer = find(customerId).orElseGet(() -> save(new LoyalCustomer(customerId, 0))); + + customers.remove(customer); + customers.add(customer.addPoints(points)); + } + + public LoyalCustomer save(LoyalCustomer customer) { + customers.add(customer); + return customer; + } + + public boolean isLoyalCustomer(String customerId) { + return find(customerId).isPresent(); + } + + public record LoyalCustomer(String customerId, int points) { + + LoyalCustomer addPoints(int points) { + return new LoyalCustomer(customerId, this.points() + points); + } + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java new file mode 100644 index 0000000000..8cd1afe329 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java @@ -0,0 +1,24 @@ +package com.baeldung.springmodulith.application.events.rewards; + +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; + +@Service +public class LoyaltyPointsService { + + public static final int ORDER_COMPLETED_POINTS = 60; + private final LoyalCustomersRepository loyalCustomers; + + public LoyaltyPointsService(LoyalCustomersRepository loyalCustomers) { + this.loyalCustomers = loyalCustomers; + } + + @EventListener + public void onOrderCompleted(OrderCompletedEvent event) { + // business logic to award points to loyal customers + loyalCustomers.awardPoints(event.customerId(), ORDER_COMPLETED_POINTS); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/Baeldung.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/Baeldung.java index 1d309a8653..4b861a49c8 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/Baeldung.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/Baeldung.java @@ -6,32 +6,29 @@ import org.springframework.transaction.annotation.Transactional; @Service public class Baeldung { + private final ApplicationEventPublisher applicationEvents; + private final ArticleRepository articleRepository; - private final ApplicationEventPublisher applicationEvents; - private final ArticleRepository articleRepository; + public Baeldung(ApplicationEventPublisher applicationEvents, ArticleRepository articleRepository) { + this.applicationEvents = applicationEvents; + this.articleRepository = articleRepository; + } + @Transactional + public void createArticle(Article article) { + // ... business logic + validateArticle(article); + article = addArticleTags(article); + article = articleRepository.save(article); - public Baeldung(ApplicationEventPublisher applicationEvents, ArticleRepository articleRepository) { - this.applicationEvents = applicationEvents; - this.articleRepository = articleRepository; - } + applicationEvents.publishEvent(new ArticlePublishedEvent(article.slug(), article.title())); + } - @Transactional - public void createArticle(Article article) { - // ... business logic - validateArticle(article); - article = addArticleTags(article); - article = articleRepository.save(article); + private Article addArticleTags(Article article) { + return article; + } - applicationEvents.publishEvent(new ArticlePublishedEvent(article.slug(), article.title())); - } - - - private Article addArticleTags(Article article) { - return article; - } - - private void validateArticle(Article article) { - } + private void validateArticle(Article article) { + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/EventExternalizationConfig.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/EventExternalizationConfig.java index 9564696d92..6555694df9 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/EventExternalizationConfig.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/EventExternalizationConfig.java @@ -4,12 +4,14 @@ import org.springframework.boot.autoconfigure.kafka.KafkaProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaOperations; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.kafka.core.ProducerFactory; -import org.springframework.kafka.core.KafkaOperations; import org.springframework.modulith.events.EventExternalizationConfiguration; import org.springframework.modulith.events.RoutingTarget; +import java.util.Objects; + @Configuration class EventExternalizationConfig { @@ -23,19 +25,30 @@ class EventExternalizationConfig { ) .mapping( ArticlePublishedEvent.class, - it -> new ArticlePublishedKafkaEvent(it.slug(), it.title()) + it -> new PostPublishedKafkaEvent(it.slug(), it.title()) + ) + .route( + WeeklySummaryPublishedEvent.class, + it -> RoutingTarget.forTarget("baeldung.articles.published").andKey(it.handle()) + ) + .mapping( + WeeklySummaryPublishedEvent.class, + it -> new PostPublishedKafkaEvent(it.handle(), it.heading()) ) .build(); } - record ArticlePublishedKafkaEvent(String slug, String title) { - } - - @Bean KafkaOperations kafkaOperations(KafkaProperties kafkaProperties) { ProducerFactory producerFactory = new DefaultKafkaProducerFactory<>(kafkaProperties.buildProducerProperties()); return new KafkaTemplate<>(producerFactory); } + + record PostPublishedKafkaEvent(String slug, String title) { + PostPublishedKafkaEvent { + Objects.requireNonNull(slug, "Article Slug must not be null!"); + } + } + } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/WeeklySummaryPublishedEvent.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/WeeklySummaryPublishedEvent.java new file mode 100644 index 0000000000..2ae8713099 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/WeeklySummaryPublishedEvent.java @@ -0,0 +1,7 @@ +package com.baeldung.springmodulith.events.externalization; + +import org.springframework.modulith.events.Externalized; + +@Externalized +record WeeklySummaryPublishedEvent(String handle, String heading) { +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/infra/PublicationEvents.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/infra/PublicationEvents.java new file mode 100644 index 0000000000..bf0b96e78b --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/events/externalization/infra/PublicationEvents.java @@ -0,0 +1,38 @@ +package com.baeldung.springmodulith.events.externalization.infra; + +import com.baeldung.springmodulith.events.externalization.ArticlePublishedEvent; +import org.springframework.modulith.events.CompletedEventPublications; +import org.springframework.modulith.events.IncompleteEventPublications; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.Instant; + +@Component +class PublicationEvents { + private final IncompleteEventPublications incompleteEvent; + private final CompletedEventPublications completeEvents; + + public PublicationEvents(IncompleteEventPublications incompleteEvent, CompletedEventPublications completeEvents) { + this.incompleteEvent = incompleteEvent; + this.completeEvents = completeEvents; + } + + public void resubmitUnpublishedEvents() { + incompleteEvent.resubmitIncompletePublicationsOlderThan(Duration.ofSeconds(60)); + + // or + incompleteEvent.resubmitIncompletePublications(it -> + it.getPublicationDate().isBefore(Instant.now().minusSeconds(60)) + && it.getEvent() instanceof ArticlePublishedEvent); + } + + public void clearPublishedEvents() { + completeEvents.deletePublicationsOlderThan(Duration.ofSeconds(60)); + + // or + completeEvents.deletePublications(it -> + it.getPublicationDate().isBefore(Instant.now().minusSeconds(60)) + && it.getEvent() instanceof ArticlePublishedEvent); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/resources/application.yml b/spring-boot-modules/spring-boot-libraries-3/src/main/resources/application.yml index ad8f7ab4e6..c6797b57d0 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/resources/application.yml +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/resources/application.yml @@ -1,4 +1,3 @@ -logging.level.org.springframework.orm.jpa: TRACE spring.kafka: bootstrap-servers: localhost:9092 @@ -10,3 +9,20 @@ spring.kafka: key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer auto-offset-reset: earliest + +spring.modulith: + republish-outstanding-events-on-restart: true + events.jdbc.schema-initialization.enabled: true + +logging.level.org.springframework.orm.jpa: TRACE + +spring: + datasource: + username: test_user + password: test_pass + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hbm2ddl.auto: create + diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java new file mode 100644 index 0000000000..676bc1173b --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.springmodulith.application.events; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Instant; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationEventPublisher; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; +import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; + +@SpringBootTest +class EventListenerUnitTest { + + @Autowired + private LoyalCustomersRepository customers; + + @Autowired + private ApplicationEventPublisher testEventPublisher; + + @Test + void whenPublishingOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints() { + OrderCompletedEvent event = new OrderCompletedEvent("order-1", "customer-1", Instant.now()); + + testEventPublisher.publishEvent(event); + + assertThat(customers.find("customer-1")) + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java new file mode 100644 index 0000000000..f4bdeee90d --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.springmodulith.application.events; + +import com.baeldung.springmodulith.application.events.orders.OrderService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +class EventPublisherUnitTest { + + @Autowired + OrderService orderService; + + @Autowired + TestEventListener testEventListener; + + @BeforeEach + void beforeEach() { + testEventListener.reset(); + } + + @Test + void whenPlacingOrder_thenPublishApplicationEvent() { + orderService.placeOrder("customer1", "product1", "product2"); + + assertThat(testEventListener.getEvents()) + .hasSize(1).first() + .hasFieldOrPropertyWithValue("customerId", "customer1") + .hasFieldOrProperty("orderId") + .hasFieldOrProperty("timestamp"); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java new file mode 100644 index 0000000000..f36a0c30e6 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.springmodulith.application.events; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; +import com.baeldung.springmodulith.application.events.orders.OrderService; +import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.modulith.test.ApplicationModuleTest; +import org.springframework.modulith.test.ApplicationModuleTest.BootstrapMode; +import org.springframework.modulith.test.Scenario; + +import java.time.Duration; +import java.time.Instant; + +import static java.time.Duration.ofMillis; +import static org.assertj.core.api.Assertions.assertThat; + +@ApplicationModuleTest +class SpringModulithScenarioApiUnitTest { + + @Autowired + OrderService orderService; + + @Autowired + LoyalCustomersRepository loyalCustomers; + + @Test + void whenPlacingOrder_thenPublishOrderCompletedEvent(Scenario scenario) { + scenario.stimulate(() -> orderService.placeOrder("customer-1", "product-1", "product-2")) + .andWaitForEventOfType(OrderCompletedEvent.class) + .toArriveAndVerify(evt -> assertThat(evt) + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrProperty("orderId") + .hasFieldOrProperty("timestamp")); + } + + @Test + void whenReceivingPublishOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints(Scenario scenario) { + scenario.publish(new OrderCompletedEvent("order-1", "customer-1", Instant.now())) + .andWaitForStateChange(() -> loyalCustomers.find("customer-1")) + .andVerify(it -> assertThat(it) + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60)); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java new file mode 100644 index 0000000000..8973a99355 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java @@ -0,0 +1,29 @@ +package com.baeldung.springmodulith.application.events; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; + +@Component +class TestEventListener { + + private final List events = new ArrayList<>(); + + @EventListener + void onEvent(OrderCompletedEvent event) { + events.add(event); + } + + public List getEvents() { + return events; + } + + public void reset() { + events.clear(); + } +} + diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/events/externalization/EventsExternalizationLiveTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/events/externalization/EventsExternalizationLiveTest.java index 7f4f7a8224..a1b3dfe170 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/events/externalization/EventsExternalizationLiveTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/events/externalization/EventsExternalizationLiveTest.java @@ -1,10 +1,8 @@ package com.baeldung.springmodulith.events.externalization; -import static java.time.Duration.ofMillis; -import static java.time.Duration.ofSeconds; -import static org.assertj.core.api.Assertions.assertThat; -import static org.testcontainers.shaded.org.awaitility.Awaitility.await; - +import com.baeldung.springmodulith.Application; +import com.baeldung.springmodulith.events.externalization.listener.TestKafkaListenerConfig; +import com.baeldung.springmodulith.events.externalization.listener.TestListener; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -12,14 +10,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.shaded.org.awaitility.Awaitility; import org.testcontainers.utility.DockerImageName; -import com.baeldung.springmodulith.Application; -import com.baeldung.springmodulith.events.externalization.listener.TestKafkaListenerConfig; -import com.baeldung.springmodulith.events.externalization.listener.TestListener; +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; @Testcontainers @SpringBootTest(classes = { Application.class, TestKafkaListenerConfig.class }) @@ -35,13 +35,20 @@ class EventsExternalizationLiveTest { @Container static KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")); + @Container + public static PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer() + .withDatabaseName("test_db") + .withUsername("test_user") + .withPassword("test_pass"); + @DynamicPropertySource static void dynamicProperties(DynamicPropertyRegistry registry) { registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.datasource.url", postgresqlContainer::getJdbcUrl); } static { - Awaitility.setDefaultTimeout(ofSeconds(3)); + Awaitility.setDefaultTimeout(ofSeconds(50)); Awaitility.setDefaultPollDelay(ofMillis(100)); } @@ -86,4 +93,4 @@ class EventsExternalizationLiveTest { .extracting(Article::title, Article::author) .containsExactly("Introduction to Spring Boot", "John Doe"); } -} \ No newline at end of file +} diff --git a/spring-boot-modules/spring-boot-logging-loki/README.md b/spring-boot-modules/spring-boot-logging-loki/README.md new file mode 100644 index 0000000000..376f9d803f --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Logging in Spring Boot With Loki](https://www.baeldung.com/spring-boot-loki-grafana-logging) diff --git a/spring-boot-modules/spring-boot-logging-loki/pom.xml b/spring-boot-modules/spring-boot-logging-loki/pom.xml new file mode 100644 index 0000000000..5b2887562b --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + spring-boot-logging-loki + 0.1-SNAPSHOT + loki + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + com.github.loki4j + loki-logback-appender + ${loki-logback.version} + + + org.springframework.boot + spring-boot-starter-test + + + org.springframework.boot + spring-boot-starter-web + + + + + 1.4.2 + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java new file mode 100644 index 0000000000..89fdcc48e8 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java @@ -0,0 +1,15 @@ +package com.baeldung.loki; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class DemoService { + + private static final Logger LOG = LoggerFactory.getLogger(DemoService.class); + + public void log() { + LOG.info("DemoService.log invoked"); + } +} diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..1ba53d7278 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml @@ -0,0 +1,32 @@ + + + + + + + http://localhost:3100/loki/api/v1/push + + + + + + { + "level":"%level", + "class":"%logger{36}", + "thread":"%thread", + "message": "%message", + "requestId": "%X{X-Request-ID}" + } + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java new file mode 100644 index 0000000000..4c44888dca --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java @@ -0,0 +1,85 @@ +package com.baeldung.loki; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URI; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest(classes = DemoService.class) +public class DemoServiceLiveTest { + + /** + * This test assumes that loki service is already up. + * For more details please check section #2 Running Loki and Grafana Service + * Which spin up Loki server using docker-compose + */ + @Test + public void givenLokiContainerRunning_whenDemoServiceInvoked_thenLokiAppenderCollectLogs() throws JsonProcessingException, InterruptedException { + DemoService service = new DemoService(); + service.log(); + + String baseUrl = "http://localhost:3100/loki/api/v1/query_range"; + // Set up query parameters + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + String query = "{level=\"INFO\"} |= `DemoService.log invoked`"; + + // Get current time in UTC + LocalDateTime currentDateTime = LocalDateTime.now(ZoneOffset.UTC); + String currentTimeUtc = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + + LocalDateTime tenMinsAgo = currentDateTime.minusMinutes(10); + String startTimeUtc = tenMinsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + + URI uri = UriComponentsBuilder.fromUriString(baseUrl) + .queryParam("query", query) + .queryParam("start", startTimeUtc) + .queryParam("end", currentTimeUtc) + .build() + .toUri(); + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(headers), String.class); + + List messages = new ArrayList<>(); + ObjectMapper objectMapper = new ObjectMapper(); + assertEquals(response.getStatusCode(), HttpStatus.OK); + + String responseBody = response.getBody(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + JsonNode result = jsonNode.get("data") + .get("result") + .get(0) + .get("values"); + result.iterator() + .forEachRemaining(e -> { + Iterator elements = e.elements(); + elements.forEachRemaining(f -> messages.add(f.toString())); + }); + + String expected = "DemoService.log invoked"; + assertThat(messages).anyMatch(e -> e.contains(expected)); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-2/pom.xml b/spring-boot-modules/spring-boot-mvc-2/pom.xml index bdf9b66a86..b6ac5bdcd7 100644 --- a/spring-boot-modules/spring-boot-mvc-2/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-2/pom.xml @@ -53,6 +53,7 @@ io.rest-assured rest-assured test + ${rest-assured-version} @@ -80,7 +81,11 @@ 3.0.0 com.baeldung.springbootmvc.SpringBootMvcFnApplication + 17 1.4.11.1 + 5.4.0 + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java index b5c0bdad12..c576c3cb1b 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java @@ -2,12 +2,9 @@ package com.baeldung.mime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; 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.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java index 6a77e72cea..351dd2344f 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java @@ -4,8 +4,9 @@ import static org.springframework.web.servlet.function.RouterFunctions.route; import static org.springframework.web.servlet.function.ServerResponse.ok; import static org.springframework.web.servlet.function.ServerResponse.status; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.baeldung.springbootmvc.SpringBootMvcFnApplication.Error; +import com.baeldung.springbootmvc.model.Product; +import com.baeldung.springbootmvc.svc.ProductService; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.servlet.function.EntityResponse; @@ -14,10 +15,6 @@ import org.springframework.web.servlet.function.RouterFunction; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; -import com.baeldung.springbootmvc.SpringBootMvcFnApplication.Error; -import com.baeldung.springbootmvc.model.Product; -import com.baeldung.springbootmvc.svc.ProductService; - @Component public class ProductController { @@ -27,10 +24,8 @@ public class ProductController { } public RouterFunction productSearch(ProductService ps) { - return route().nest(RequestPredicates.path("/product"), builder -> { - builder.GET("/name/{name}", req -> ok().body(ps.findByName(req.pathVariable("name")))) - .GET("/id/{id}", req -> ok().body(ps.findById(Integer.parseInt(req.pathVariable("id"))))); - }) + return route().nest(RequestPredicates.path("/product"), builder -> builder.GET("/name/{name}", req -> ok().body(ps.findByName(req.pathVariable("name")))) + .GET("/id/{id}", req -> ok().body(ps.findById(Integer.parseInt(req.pathVariable("id")))))) .onError(ProductService.ItemNotFoundException.class, (e, req) -> EntityResponse.fromObject(new Error(e.getMessage())) .status(HttpStatus.NOT_FOUND) .build()) diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java index e2d281d54f..5be5f67a37 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java @@ -38,7 +38,7 @@ public class ProductService { } public Product save(Product product) { - if (StringUtils.isEmpty(product.getName()) || product.getPrice() == 0.0) { + if (!StringUtils.hasLength(product.getName()) || product.getPrice() == 0.0) { throw new IllegalArgumentException(); } int newId = products.stream() diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java index 80f6dfd514..f42c61077c 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java @@ -19,7 +19,7 @@ public class StudentService { new Student(2, "Sebastian","Bach"), new Student(3, "Pablo","Picasso"), }).stream() - .collect(Collectors.toConcurrentMap(s -> s.getId(), Function.identity())); + .collect(Collectors.toConcurrentMap(Student::getId, Function.identity())); // DB id sequence mock private AtomicLong sequence = new AtomicLong(3); diff --git a/spring-boot-modules/spring-boot-mvc-5/pom.xml b/spring-boot-modules/spring-boot-mvc-5/pom.xml index 10a58a6a59..3a45d58831 100644 --- a/spring-boot-modules/spring-boot-mvc-5/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-5/pom.xml @@ -65,22 +65,17 @@ JAR - - org.apache.maven.plugins - maven-compiler-plugin - - 9 - 9 - - + 3.2.2 + 5.10.2 3.0.0 com.baeldung.springboot.swagger.ArticleApplication - 2021.0.5 + 2023.0.0 1.10 + 17 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java index 66fce3c3e2..1d65b73e8e 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java @@ -5,6 +5,9 @@ import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.*; +import java.util.Collections; +import java.util.Enumeration; +import org.springframework.http.HttpHeaders; public class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper { private String body = null; @@ -64,4 +67,12 @@ public class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper { public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } + + @Override + public Enumeration getHeaders(String name) { + if(HttpHeaders.CONTENT_LENGTH.equals(name)) { + return Collections.enumeration(Collections.singletonList(String.valueOf(body.length()))); + } + return super.getHeaders(name); + } } diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java index ef18591ccb..fe212bf6b1 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -45,6 +46,7 @@ public class EscapeHtmlAspectIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save")) .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_LENGTH, 100) .content(objectMapper.writeValueAsString(requestBody))) .andExpect(MockMvcResultMatchers.status() .isCreated()) diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java index c813827422..ff37cb6217 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java @@ -1,5 +1,6 @@ package com.baeldung.modifyrequest; +import com.baeldung.modifyrequest.config.WebMvcConfiguration; import com.baeldung.modifyrequest.controller.UserController; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; @@ -9,6 +10,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -21,7 +23,7 @@ import java.util.Map; @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc -@WebMvcTest(UserController.class) +@WebMvcTest(value ={UserController.class, WebMvcConfiguration.class}) @ActiveProfiles("filterExample") public class EscapeHtmlFilterIntegrationTest { Logger logger = LoggerFactory.getLogger(EscapeHtmlFilterIntegrationTest.class); @@ -44,6 +46,7 @@ public class EscapeHtmlFilterIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save")) .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_LENGTH, "100") .content(objectMapper.writeValueAsString(requestBody))).andExpect(MockMvcResultMatchers.status() .isCreated()).andExpect(MockMvcResultMatchers.content() .json(objectMapper.writeValueAsString(expectedResponseBody))); diff --git a/spring-boot-modules/spring-boot-mvc/pom.xml b/spring-boot-modules/spring-boot-mvc/pom.xml index ab1c867d66..ec084df714 100644 --- a/spring-boot-modules/spring-boot-mvc/pom.xml +++ b/spring-boot-modules/spring-boot-mvc/pom.xml @@ -52,8 +52,8 @@ org.glassfish - javax.faces - ${javax.faces.version} + jakarta.faces + ${jakarta.faces.version} @@ -73,8 +73,9 @@ hibernate-validator - javax.validation - validation-api + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.version} org.springframework.boot @@ -112,8 +113,9 @@ 1.10.0 - 2.3.7 + 4.1.0-M1 1.9.20.1 + 3.1.0-M1 com.baeldung.springbootmvc.SpringBootMvcApplication diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java index b1bdc7d781..049fcc986f 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java @@ -1,8 +1,8 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; @WebListener public class AttrListener implements ServletContextListener { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java index d8192c2cb1..89b948ba87 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java @@ -1,9 +1,10 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import java.io.File; import java.io.IOException; import java.nio.file.Files; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java index 146e5ae386..f6472174a2 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java @@ -1,8 +1,9 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.*; -import javax.servlet.annotation.WebFilter; -import javax.servlet.annotation.WebInitParam; +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.annotation.WebInitParam; + import java.io.IOException; @WebFilter(urlPatterns = "/hello", description = "a filter for hello servlet", initParams = { @WebInitParam(name = "msg", value = "filtering ") }, filterName = "hello filter", servletNames = { "echo servlet" }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java index 5269c1bf29..8caa798e76 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java @@ -1,11 +1,12 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.ServletConfig; -import javax.servlet.annotation.WebInitParam; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.annotation.WebInitParam; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; @WebServlet(urlPatterns = "/hello", initParams = { @WebInitParam(name = "msg", value = "hello") }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java index c3af611f3b..2fdd79d060 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java @@ -1,7 +1,7 @@ package com.baeldung.internationalization; -import javax.annotation.security.RolesAllowed; +import jakarta.annotation.security.RolesAllowed; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java index 098c5e4794..19246e3014 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java @@ -3,8 +3,7 @@ package com.baeldung.responseentity; import java.io.IOException; import java.time.Year; -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java index e37e2c9d78..c0bfd641d4 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.config; -import javax.validation.MessageInterpolator; - +import jakarta.validation.MessageInterpolator; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java index 003a3d79b0..a81c19148a 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java @@ -4,8 +4,7 @@ import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.validation.MessageInterpolator; - +import jakarta.validation.MessageInterpolator; import org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java index f9a7d1a9b5..eff81f6dda 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.service1; -import javax.validation.constraints.NotEmpty; - +import jakarta.validation.constraints.NotEmpty; import lombok.*; @Data diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java index 790b5031e6..6883e539f8 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java @@ -1,5 +1,6 @@ package com.baeldung.restvalidation.service1; +import jakarta.validation.Valid; import org.springframework.http.*; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; @@ -7,8 +8,6 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - import com.baeldung.restvalidation.response.InputFieldError; import com.baeldung.restvalidation.response.UpdateUserResponse; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java index a2e567766c..dd9584e27b 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.service2; -import javax.validation.constraints.NotEmpty; - +import jakarta.validation.constraints.NotEmpty; import lombok.*; @Data diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java index 4593a2b1bd..78ec60720d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java @@ -3,8 +3,7 @@ package com.baeldung.restvalidation.service2; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java index 93c7052d5b..03392af45c 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java @@ -1,5 +1,8 @@ package com.baeldung.restvalidation.service3; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; @@ -12,8 +15,6 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; @Documented @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java index 356efc590b..5d4b188911 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java @@ -1,7 +1,7 @@ package com.baeldung.restvalidation.service3; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class FieldNotEmptyValidator implements ConstraintValidator { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java index e506b63d8e..3efb88c29d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java @@ -3,8 +3,7 @@ package com.baeldung.restvalidation.service3; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java index c9b9c51bec..8cfb9b9931 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java @@ -6,9 +6,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.view.feed.AbstractRssFeedView; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java index 62b1329a54..d3d3cb44d5 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java @@ -3,9 +3,9 @@ package com.baeldung.springbootannotations; import java.util.Arrays; import java.util.Properties; -import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; +import jakarta.persistence.EntityManagerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionMessage; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java index 589024c0bc..190e882781 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java @@ -1,7 +1,6 @@ package com.baeldung.springbootmvc; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java index 5b4250d5e3..86265b0b4d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java @@ -1,7 +1,6 @@ package com.baeldung.springbootmvc.jsfapplication; -import javax.faces.webapp.FacesServlet; - +import jakarta.faces.webapp.FacesServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java index 107cd1bbf1..274265e97b 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java @@ -1,8 +1,8 @@ package com.baeldung.springbootmvc.model; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; public class LoginForm { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties index 90d3c88a8f..f8e1a6a434 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties @@ -1 +1 @@ -javax.validation.constraints.NotEmpty.message=The field cannot be empty \ No newline at end of file +jakarta.validation.constraints.NotEmpty.message=The field cannot be empty \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties index 04f415911c..5c7bfbcb36 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties @@ -1 +1 @@ -javax.validation.constraints.NotEmpty.message=本欄不能留空 \ No newline at end of file +jakarta.validation.constraints.NotEmpty.message=本欄不能留空 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml b/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml index e0cd4d8850..45d30565fe 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml +++ b/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml @@ -7,7 +7,7 @@ Faces Servlet - javax.faces.webapp.FacesServlet + jakarta.faces.webapp.FacesServlet 1 diff --git a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java index 92223892d9..230fe200e6 100644 --- a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java @@ -4,9 +4,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import javax.servlet.FilterRegistration; -import javax.servlet.ServletContext; - +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.ServletContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java index c29cd75e9d..0d413be91e 100644 --- a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java @@ -4,9 +4,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import javax.servlet.FilterRegistration; -import javax.servlet.ServletContext; - +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.ServletContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-boot-modules/spring-boot-openapi/README.md b/spring-boot-modules/spring-boot-openapi/README.md new file mode 100644 index 0000000000..cdfe6cf1a8 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [OpenAPI Generator Custom Templates](https://www.baeldung.com/spring-boot-openapi-generator-custom-templates) diff --git a/spring-boot-modules/spring-boot-openapi/pom.xml b/spring-boot-modules/spring-boot-openapi/pom.xml new file mode 100644 index 0000000000..f1cf98e4b5 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + spring-boot-openapi + spring-boot-openapi + jar + OpenAPI Generator module + + + org.springframework.boot + spring-boot-starter-parent + 2.7.11 + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-validation + + + javax.validation + validation-api + + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + + + + + + org.openapitools + openapi-generator-maven-plugin + ${openapi-generator.version} + + + + generate + + + true + ${project.basedir}/src/main/resources/api/quotes.yaml + spring + ApiUtil.java + ${project.basedir}/src/main/resources/templates/JavaSpring + + true + + + java8 + false + true + com.baeldung.tutorials.openapi.quotes.api + com.baeldung.tutorials.openapi.quotes.api.model + source + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 17 + 17 + 7.3.0 + 2.2.20 + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java new file mode 100644 index 0000000000..37d8278133 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.tutorials.openapi.quotes; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; + +import com.baeldung.tutorials.openapi.quotes.service.BrokerService; + +@SpringBootApplication +@EnableCaching +public class QuotesApplication { + + public static void main(String[] args) { + SpringApplication.run(QuotesApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/config/ClockConfiguration.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/config/ClockConfiguration.java new file mode 100644 index 0000000000..60eb6fc967 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/config/ClockConfiguration.java @@ -0,0 +1,17 @@ +package com.baeldung.tutorials.openapi.quotes.config; + +import java.time.Clock; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ClockConfiguration { + + @Bean + @ConditionalOnMissingBean + Clock defaultClock() { + return Clock.systemDefaultZone(); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java new file mode 100644 index 0000000000..f0e4d5c33f --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java @@ -0,0 +1,45 @@ +package com.baeldung.tutorials.openapi.quotes.controller; + +import java.time.Clock; +import java.time.OffsetDateTime; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import com.baeldung.tutorials.openapi.quotes.api.QuotesApi; +import com.baeldung.tutorials.openapi.quotes.api.QuotesApiDelegate; +import com.baeldung.tutorials.openapi.quotes.api.model.QuoteResponse; +import com.baeldung.tutorials.openapi.quotes.service.BrokerService; + +@Component +public class QuotesApiImpl implements QuotesApiDelegate { + private final BrokerService broker; + private final Clock clock; + + public QuotesApiImpl(BrokerService broker, Clock clock) { + this.broker = broker; + this.clock = clock; + } + + + /** + * GET /quotes/{symbol} : Get current quote for a security + * + * @param symbol Security's symbol (required) + * @return OK (status code 200) + * @see QuotesApi#getQuote + */ + @Override + public ResponseEntity getQuote(String symbol) { + + var price = broker.getSecurityPrice(symbol); + + var quote = new QuoteResponse(); + quote.setSymbol(symbol); + quote.setPrice(price); + quote.setTimestamp(OffsetDateTime.now(clock)); + return ResponseEntity.ok(quote); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java new file mode 100644 index 0000000000..f7520b098d --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java @@ -0,0 +1,32 @@ +package com.baeldung.tutorials.openapi.quotes.service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +@Service +public class BrokerService { + + private final Logger log = LoggerFactory.getLogger(BrokerService.class); + + private final Random rnd = new Random(); + + + public BrokerService() { + } + + + public BigDecimal getSecurityPrice(@NonNull String symbol) { + log.info("getSecurityPrice: {}", symbol); + // Just a mock value + return BigDecimal.valueOf(100.0 + rnd.nextDouble()*100.0); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml b/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml new file mode 100644 index 0000000000..590fe661ad --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml @@ -0,0 +1,54 @@ +openapi: 3.0.0 +info: + title: Quotes API + version: 1.0.0 +servers: + - description: Test server + url: http://localhost:8080 +paths: + /quotes/{symbol}: + get: + tags: + - quotes + summary: Get current quote for a security + operationId: getQuote + x-spring-cacheable: + name: get-quotes + security: + - ApiKey: + - Quotes.Read + parameters: + - name: symbol + in: path + required: true + description: Security's symbol + schema: + type: string + pattern: '[A-Z0-9]+' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuoteResponse' +components: + securitySchemes: + ApiKey: + type: apiKey + in: header + name: X-API-KEY + schemas: + QuoteResponse: + description: Quote response + type: object + properties: + symbol: + type: string + description: security's symbol + price: + type: number + description: Quote value + timestamp: + type: string + format: date-time \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml b/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml new file mode 100644 index 0000000000..c177283306 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml @@ -0,0 +1,5 @@ + +logging: + level: + root: INFO + org.springframework: INFO \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-openapi/src/main/resources/templates/JavaSpring/apiDelegate.mustache b/spring-boot-modules/spring-boot-openapi/src/main/resources/templates/JavaSpring/apiDelegate.mustache new file mode 100644 index 0000000000..a26fb3556d --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/resources/templates/JavaSpring/apiDelegate.mustache @@ -0,0 +1,84 @@ +/* +* Generated code: do not modify ! +* Custom template with support for x-spring-cacheable extension +*/ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +{{#useResponseEntity}} + import org.springframework.http.ResponseEntity; +{{/useResponseEntity}} +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.multipart.MultipartFile; +{{#reactive}} + import org.springframework.web.server.ServerWebExchange; + import reactor.core.publisher.Flux; + import reactor.core.publisher.Mono; + import org.springframework.http.codec.multipart.Part; +{{/reactive}} + +{{#useBeanValidation}} + import {{javaxPackage}}.validation.constraints.*; + import {{javaxPackage}}.validation.Valid; +{{/useBeanValidation}} +import java.util.List; +import java.util.Map; +import java.util.Optional; +{{#async}} + import java.util.concurrent.CompletableFuture; +{{/async}} +import {{javaxPackage}}.annotation.Generated; + +{{#operations}} + /** + * A delegate to be called by the {@link {{classname}}Controller}}. + * Implement this interface with a {@link org.springframework.stereotype.Service} annotated class. + */ + {{>generatedAnnotation}} + public interface {{classname}}Delegate { + {{#jdk8-default-interface}} + + default Optional getRequest() { + return Optional.empty(); + } + {{/jdk8-default-interface}} + + {{#operation}} + /** + * {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}} + {{#notes}} + * {{.}} + {{/notes}} + * + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} + * or {{/-last}}{{/responses}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + * @see {{classname}}#{{operationId}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#vendorExtensions.x-spring-cacheable}} + @org.springframework.cache.annotation.Cacheable({{#name}}"{{.}}"{{/name}}{{^name}}"default"{{/name}}) + {{/vendorExtensions.x-spring-cacheable}} + {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{>responseType}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#isArray}}List<{{/isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}}{{/isFile}} {{paramName}}{{^-last}}, + {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, + {{/hasParams}}ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} { + {{>methodBody}} + }{{/jdk8-default-interface}} + + {{/operation}} + } +{{/operations}} diff --git a/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/QuotesApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/QuotesApplicationIntegrationTest.java new file mode 100644 index 0000000000..b1defb99b1 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/QuotesApplicationIntegrationTest.java @@ -0,0 +1,45 @@ +package com.baeldung.tutorials.openapi.quotes; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.Test; +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.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpStatus; + +import com.baeldung.tutorials.openapi.quotes.api.model.QuoteResponse; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class QuotesApplicationIntegrationTest { + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void whenGetQuote_thenSuccess() { + var response = restTemplate.getForEntity("http://localhost:" + port + "/quotes/BAEL", QuoteResponse.class); + assertThat(response.getStatusCode()) + .isEqualTo(HttpStatus.OK); + } + + @Test + void whenGetQuoteMultipleTimes_thenResponseCached() { + + // Call server a few times and collect responses + var quotes = IntStream.range(1, 10).boxed() + .map((i) -> restTemplate.getForEntity("http://localhost:" + port + "/quotes/BAEL", QuoteResponse.class)) + .map(HttpEntity::getBody) + .collect(Collectors.groupingBy((q -> q.hashCode()), Collectors.counting())); + + assertThat(quotes.size()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImplUnitTest.java b/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImplUnitTest.java new file mode 100644 index 0000000000..01e37ef104 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/test/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImplUnitTest.java @@ -0,0 +1,55 @@ +package com.baeldung.tutorials.openapi.quotes.controller; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Clock; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import com.baeldung.tutorials.openapi.quotes.api.QuotesApi; + +@SpringBootTest +class QuotesApiImplUnitTest { + + @Autowired + private QuotesApi api; + + + private static Instant NOW = Instant.now(); + + @Test + void whenGetQuote_then_success() { + + var response = api.getQuote("GOOG"); + assertThat(response) + .isNotNull(); + + assertThat(response.getStatusCode().is2xxSuccessful()) + .isTrue(); + + assertThat(response.getBody().getTimestamp()) + .isEqualTo(OffsetDateTime.ofInstant(NOW, ZoneId.systemDefault())); + } + + + @TestConfiguration + @EnableCaching + static class TestConfig { + + @Bean + @Primary + Clock fixedClock() { + return Clock.fixed(NOW, ZoneId.systemDefault()); + } + + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml index 61892fd076..ccf276471f 100644 --- a/spring-boot-modules/spring-boot-properties/pom.xml +++ b/spring-boot-modules/spring-boot-properties/pom.xml @@ -37,11 +37,6 @@ org.springframework.cloud spring-cloud-starter - - com.google.guava - guava - ${guava.version} - org.apache.httpcomponents httpcore diff --git a/spring-boot-modules/spring-boot-react/pom.xml b/spring-boot-modules/spring-boot-react/pom.xml index 95ae8c59d2..b808e4a32d 100644 --- a/spring-boot-modules/spring-boot-react/pom.xml +++ b/spring-boot-modules/spring-boot-react/pom.xml @@ -244,7 +244,6 @@ 1.6 v14.18.0 v1.12.1 - 2.4.4 1.0.2 diff --git a/spring-boot-modules/spring-boot-react/src/main/java/com/baeldung/springbootreact/domain/Client.java b/spring-boot-modules/spring-boot-react/src/main/java/com/baeldung/springbootreact/domain/Client.java index 46e7c29fd5..f600406a0a 100644 --- a/spring-boot-modules/spring-boot-react/src/main/java/com/baeldung/springbootreact/domain/Client.java +++ b/spring-boot-modules/spring-boot-react/src/main/java/com/baeldung/springbootreact/domain/Client.java @@ -1,9 +1,9 @@ package com.baeldung.springbootreact.domain; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; @Entity @Table(name = "client") diff --git a/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java b/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java index 6fbd140981..8f59c5bd65 100644 --- a/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java +++ b/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java @@ -13,6 +13,11 @@ public class RedisTestConfiguration { public RedisTestConfiguration(RedisProperties redisProperties) { this.redisServer = new RedisServer(redisProperties.getPort()); + // To run on windows uncomment the following lines + // this.redisServer = RedisServer.builder().setting("maxheap 200m") + // .port(redisProperties.getPort()) + // .setting("bind localhost") + // .build(); } @PostConstruct diff --git a/spring-boot-modules/spring-boot-resilience4j/pom.xml b/spring-boot-modules/spring-boot-resilience4j/pom.xml index 2f3af8f9d2..809afc1aa4 100644 --- a/spring-boot-modules/spring-boot-resilience4j/pom.xml +++ b/spring-boot-modules/spring-boot-resilience4j/pom.xml @@ -29,8 +29,8 @@ io.github.resilience4j - resilience4j-spring-boot2 - ${resilience4j-spring-boot2.version} + resilience4j-spring-boot3 + ${resilience4j-spring-boot3.version} com.fasterxml.jackson.datatype @@ -43,17 +43,17 @@ test - com.github.tomakehurst - wiremock-jre8 - ${wiremock-jre8.version} + org.wiremock + wiremock + ${wiremock.version} test - 2.35.0 - 2.0.2 - 2.16.0 + 3.4.2 + 2.2.0 + 2.16.1 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime-2/pom.xml b/spring-boot-modules/spring-boot-runtime-2/pom.xml index 356880975a..c925735817 100644 --- a/spring-boot-modules/spring-boot-runtime-2/pom.xml +++ b/spring-boot-modules/spring-boot-runtime-2/pom.xml @@ -75,5 +75,6 @@ 3.1.3 + com.baeldung.heap.HeapSizeDemoApplication \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime/pom.xml b/spring-boot-modules/spring-boot-runtime/pom.xml index 7b2ed6976b..e43d6b0eb0 100644 --- a/spring-boot-modules/spring-boot-runtime/pom.xml +++ b/spring-boot-modules/spring-boot-runtime/pom.xml @@ -69,13 +69,8 @@ runtime - javax.persistence - javax.persistence-api - - - com.google.guava - guava - ${guava.version} + jakarta.persistence + jakarta.persistence-api org.subethamail @@ -84,14 +79,16 @@ test - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 + 5.3.1 3.1.7 3.1.3 + com.baeldung.shutdown.Application \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java index 11ea5b70c9..9539b17c88 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java @@ -4,7 +4,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java index 321f3be3ef..0f596f5816 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java @@ -1,6 +1,6 @@ package com.baeldung.sampleapp.web.controller.redirect; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/shutdown/TerminateBean.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/shutdown/TerminateBean.java index 4f3b81b920..1a0288b3dc 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/shutdown/TerminateBean.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/shutdown/TerminateBean.java @@ -1,6 +1,6 @@ package com.baeldung.shutdown; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; public class TerminateBean { diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/logging/SecurityConfig.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/logging/SecurityConfig.java index 6870f4e6bb..03f4959fbc 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/logging/SecurityConfig.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/logging/SecurityConfig.java @@ -9,8 +9,8 @@ import org.springframework.security.web.SecurityFilterChain; public class SecurityConfig { @Bean public SecurityFilterChain securityFilter(HttpSecurity http) throws Exception { - return http.csrf() - .ignoringAntMatchers("/actuator/**").and() + return http + .csrf(csrf -> csrf.ignoringRequestMatchers("/actuator/**") ) .build(); } } diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java index d85c043dc0..6dd2ab446b 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java @@ -4,22 +4,23 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import org.springframework.boot.actuate.trace.http.HttpTrace; -import org.springframework.boot.actuate.trace.http.HttpTraceRepository; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.springframework.boot.actuate.web.exchanges.HttpExchange; +import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; import org.springframework.stereotype.Repository; @Repository -public class CustomTraceRepository implements HttpTraceRepository { +public class CustomTraceRepository implements HttpExchangeRepository { - AtomicReference lastTrace = new AtomicReference<>(); + AtomicReference lastTrace = new AtomicReference<>(); @Override - public List findAll() { + public List findAll() { return Collections.singletonList(lastTrace.get()); } @Override - public void add(HttpTrace trace) { + public void add(HttpExchange trace) { if ("GET".equals(trace.getRequest() .getMethod())) { lastTrace.set(trace); diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java index fd6312df47..285c538580 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java @@ -1,23 +1,22 @@ package com.baeldung.spring.boot.management.trace; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; -import org.springframework.boot.actuate.trace.http.HttpExchangeTracer; -import org.springframework.boot.actuate.trace.http.HttpTraceRepository; -import org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter; +import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; +import org.springframework.boot.actuate.web.exchanges.Include; +import org.springframework.boot.actuate.web.exchanges.servlet.HttpExchangesFilter; import org.springframework.stereotype.Component; @Component -public class TraceRequestFilter extends HttpTraceFilter { +public class TraceRequestFilter extends HttpExchangesFilter { /** - * Create a new {@link HttpTraceFilter} instance. + * Create a new {@link HttpExchangesFilter} instance. * * @param repository the trace repository - * @param tracer used to trace exchanges */ - public TraceRequestFilter(HttpTraceRepository repository, HttpExchangeTracer tracer) { - super(repository, tracer); + public TraceRequestFilter(HttpExchangeRepository repository) { + super(repository, Include.defaultIncludes()); } @Override diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedHttpServletRequest.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedHttpServletRequest.java index 51bbd51ea8..cc2257701a 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedHttpServletRequest.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedHttpServletRequest.java @@ -2,9 +2,9 @@ package com.baeldung.web.log.app; import org.springframework.util.StreamUtils; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.*; public class CachedHttpServletRequest extends HttpServletRequestWrapper { diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedServletInputStream.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedServletInputStream.java index 673d04876b..fcea7b96cf 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedServletInputStream.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/CachedServletInputStream.java @@ -3,8 +3,8 @@ package com.baeldung.web.log.app; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/RequestCachingFilter.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/RequestCachingFilter.java index e0928550fc..607404831a 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/RequestCachingFilter.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/RequestCachingFilter.java @@ -8,11 +8,11 @@ import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java index b1ddf16dfe..9c5cc731e2 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java @@ -1,6 +1,6 @@ package com.baeldung.web.log.controller; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/spring-boot-modules/spring-boot-security/src/test/resources/application.properties b/spring-boot-modules/spring-boot-security/src/test/resources/application.properties index 88bc213245..5494069009 100644 --- a/spring-boot-modules/spring-boot-security/src/test/resources/application.properties +++ b/spring-boot-modules/spring-boot-security/src/test/resources/application.properties @@ -1,2 +1,2 @@ -logging.level.root=DEBUG +logging.level.root=ERROR logging.level.com.baeldung.integrationtesting=ERROR diff --git a/spring-boot-modules/spring-boot-springdoc/pom.xml b/spring-boot-modules/spring-boot-springdoc/pom.xml index 8ed9b7c22b..567ff5a606 100644 --- a/spring-boot-modules/spring-boot-springdoc/pom.xml +++ b/spring-boot-modules/spring-boot-springdoc/pom.xml @@ -119,10 +119,11 @@ - 1.7.0 - 1.5.6 + 1.8.0 + 2.2.6 ${project.build.directory}/generated-snippets 1.4 + true \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/DefaultGlobalSecuritySchemeApplication.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/DefaultGlobalSecuritySchemeApplication.java index 1ce81a1e83..fda191f785 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/DefaultGlobalSecuritySchemeApplication.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/DefaultGlobalSecuritySchemeApplication.java @@ -19,7 +19,7 @@ import io.swagger.v3.oas.annotations.security.SecurityScheme; public class DefaultGlobalSecuritySchemeApplication { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.antMatchers("/api/auth/**", "/swagger-ui-custom.html", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**", "/swagger-ui/index.html", "/api-docs/**") + return http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.requestMatchers("/api/auth/**", "/swagger-ui-custom.html", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**", "/swagger-ui/index.html", "/api-docs/**") .permitAll() .anyRequest() .authenticated()) diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/controller/DefaultGlobalSecuritySchemeOpenApiController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/controller/DefaultGlobalSecuritySchemeOpenApiController.java index 4ad7a2a2c3..9b3d6ef545 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/controller/DefaultGlobalSecuritySchemeOpenApiController.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/controller/DefaultGlobalSecuritySchemeOpenApiController.java @@ -3,7 +3,7 @@ package com.baeldung.defaultglobalsecurityscheme.controller; import java.time.OffsetDateTime; import java.time.ZoneOffset; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/LoginDto.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/LoginDto.java index cf88cc4d98..c7c71a67a3 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/LoginDto.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/LoginDto.java @@ -1,5 +1,6 @@ package com.baeldung.defaultglobalsecurityscheme.dto; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonProperty; @@ -30,7 +31,7 @@ public class LoginDto { * @return user */ - @Schema(name = "user", required = true) + @Schema(name = "user", requiredMode = RequiredMode.REQUIRED) public String getUser() { return user; } diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/PingResponseDto.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/PingResponseDto.java index 0d367785d8..0944dce438 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/PingResponseDto.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/defaultglobalsecurityscheme/dto/PingResponseDto.java @@ -1,9 +1,10 @@ package com.baeldung.defaultglobalsecurityscheme.dto; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; import java.time.OffsetDateTime; import java.util.Objects; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.format.annotation.DateTimeFormat; @@ -33,7 +34,7 @@ public class PingResponseDto { * @return pong */ @Valid - @Schema(name = "pong", required = false) + @Schema(name = "pong", requiredMode = RequiredMode.REQUIRED) public OffsetDateTime getPong() { return pong; } diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/jwt/SecurityConfiguration.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/jwt/SecurityConfiguration.java index 8cb1ca1f60..e6c849ac45 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/jwt/SecurityConfiguration.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/jwt/SecurityConfiguration.java @@ -9,6 +9,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; @@ -53,15 +54,15 @@ public class SecurityConfiguration { return http .authorizeHttpRequests(authorizeRequests -> authorizeRequests - .antMatchers("/api/auth/**", "/swagger-ui-custom.html" ,"/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**", + .requestMatchers("/api/auth/**", "/swagger-ui-custom.html" ,"/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**", "/swagger-ui/index.html","/api-docs/**") .permitAll() .anyRequest() .authenticated()) - .cors().disable() - .csrf().disable() - .formLogin().disable() - .httpBasic().disable() + .cors(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable) + .formLogin(AbstractHttpConfigurer::disable) + .httpBasic(AbstractHttpConfigurer::disable) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/Foo.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/Foo.java index 99d63581be..cd58c4644c 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/Foo.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/Foo.java @@ -1,10 +1,10 @@ package com.baeldung.restdocopenapi; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; @Entity public class Foo { diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooController.java index 892eb05f8d..c6bfd42b73 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooController.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooController.java @@ -5,7 +5,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import java.util.List; import java.util.Optional; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooRepository.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooRepository.java index 105b57b2ef..d4691c1f51 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooRepository.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/FooRepository.java @@ -1,9 +1,10 @@ package com.baeldung.restdocopenapi; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; @Repository -public interface FooRepository extends PagingAndSortingRepository{ +public interface FooRepository extends JpaRepository { } diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/springdoc/FooBarController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/springdoc/FooBarController.java index 8af414c8fd..8e8e9f4a9e 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/springdoc/FooBarController.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/restdocopenapi/springdoc/FooBarController.java @@ -5,7 +5,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import java.util.List; import java.util.Optional; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java index f2355a2ec3..d9e4fb1c7d 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java @@ -2,8 +2,8 @@ package com.baeldung.springdoc.controller; import java.util.Collection; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import com.baeldung.springdoc.exception.BookNotFoundException; import com.baeldung.springdoc.model.Book; diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/Foo.kt b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/Foo.kt index 3bc3c8fe61..e40bcfde97 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/Foo.kt +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/Foo.kt @@ -1,10 +1,9 @@ package com.baeldung.springdoc.kotlin -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.Id -import javax.validation.constraints.NotBlank -import javax.validation.constraints.Size +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size @Entity data class Foo( diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/FooController.kt b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/FooController.kt index d3ecd6a6ba..e253e92a6d 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/FooController.kt +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/kotlin/FooController.kt @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Content import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses +import org.hibernate.internal.util.collections.CollectionHelper import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -13,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/") class FooController() { - val fooList: List = listOf(Foo(1, "one"), Foo(2, "two")) + val fooList: List = CollectionHelper.listOf(Foo(1, "one"), Foo(2, "two")) @Operation(summary = "Get all foos") @ApiResponses(value = [ diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java index 8f678a7ec2..e2c473058a 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java @@ -1,7 +1,7 @@ package com.baeldung.springdoc.model; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; public class Book { diff --git a/spring-boot-modules/spring-boot-springdoc/src/test/java/com/baeldung/jwt/OpenApiJwtIntegrationTest.java b/spring-boot-modules/spring-boot-springdoc/src/test/java/com/baeldung/jwt/OpenApiJwtIntegrationTest.java index a4920914fd..85ddefcc4c 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/test/java/com/baeldung/jwt/OpenApiJwtIntegrationTest.java +++ b/spring-boot-modules/spring-boot-springdoc/src/test/java/com/baeldung/jwt/OpenApiJwtIntegrationTest.java @@ -1,11 +1,13 @@ package com.baeldung.jwt; +import org.junit.Ignore; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; 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.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -15,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @DisplayName("OpenAPI JWT Live Tests") +@Disabled class OpenApiJwtIntegrationTest { @LocalServerPort diff --git a/spring-boot-modules/spring-boot-swagger/pom.xml b/spring-boot-modules/spring-boot-swagger/pom.xml index 668c9d561f..bd74c3ea88 100644 --- a/spring-boot-modules/spring-boot-swagger/pom.xml +++ b/spring-boot-modules/spring-boot-swagger/pom.xml @@ -10,9 +10,10 @@ Module For Spring Boot Swagger - com.baeldung.spring-boot-modules - spring-boot-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + ../../parent-boot-3 + 0.0.1-SNAPSHOT @@ -30,6 +31,11 @@ springdoc-openapi-ui ${springdoc.version} + + jakarta.ws.rs + jakarta.ws.rs-api + ${jakarta.ws.rs-api.version} + @@ -82,6 +88,8 @@ 3.1.1 1.7.0 + 3.1.0 + com.baeldung.swaggerexample.SwaggerExampleApplication \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java index 7b7bfdc2c5..9b142d3802 100644 --- a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java @@ -5,9 +5,9 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; @Api @Path(value="/hire") diff --git a/spring-boot-modules/spring-boot-telegram/baeldungbot b/spring-boot-modules/spring-boot-telegram/baeldungbot deleted file mode 100644 index 75faf49e5e..0000000000 Binary files a/spring-boot-modules/spring-boot-telegram/baeldungbot and /dev/null differ diff --git a/spring-boot-modules/spring-boot-testing-2/README.md b/spring-boot-modules/spring-boot-testing-2/README.md index fbf708381b..8db050228d 100644 --- a/spring-boot-modules/spring-boot-testing-2/README.md +++ b/spring-boot-modules/spring-boot-testing-2/README.md @@ -14,5 +14,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Boot – Testing Redis With Testcontainers](https://www.baeldung.com/spring-boot-redis-testcontainers) - [Spring Boot – Keycloak Integration Testing with Testcontainers](https://www.baeldung.com/spring-boot-keycloak-integration-testing) - [Difference Between @Spy and @SpyBean](https://www.baeldung.com/spring-spy-vs-spybean) -- [Overriding Spring Beans in Integration Test](https://www.baeldung.com/overriding-spring-beans-in-integration-test) +- [Overriding Spring Beans in Integration Test](https://www.baeldung.com/spring-beans-integration-test-override) - More articles: [[<-- prev]](../spring-boot-testing) diff --git a/spring-boot-modules/spring-boot-testing-2/pom.xml b/spring-boot-modules/spring-boot-testing-2/pom.xml index f684d7ce97..48a7c90b0a 100644 --- a/spring-boot-modules/spring-boot-testing-2/pom.xml +++ b/spring-boot-modules/spring-boot-testing-2/pom.xml @@ -78,14 +78,21 @@ ${testcontainers-redis-junit-jupiter.version} test + + io.rest-assured + rest-assured + ${rest-assured.version} + test + + - org.jvnet.jaxb2.maven2 - maven-jaxb2-plugin - ${maven-jaxb2-plugin.version} + org.jvnet.jaxb + jaxb-maven-plugin + 4.0.0 xjc @@ -107,11 +114,12 @@ com.baeldung.boot.Application - 3.1.3 - 1.17.2 - 1.10.0 + 4.0.10 + 1.19.7 + 3.3.0 1.4.6 - 0.15.1 + 0.15.3 + 5.4.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java index c3ba5c04a8..16b976b152 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java @@ -1,21 +1,23 @@ package com.baeldung.webservice; -import com.baeldung.webservice.generated.GetProductRequest; -import com.baeldung.webservice.generated.GetProductResponse; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.RequestPayload; import org.springframework.ws.server.endpoint.annotation.ResponsePayload; +import com.baeldung.webservice.generated.GetProductRequest; +import com.baeldung.webservice.generated.GetProductResponse; + @Endpoint public class ProductEndpoint { private static final String NAMESPACE_URI = "http://baeldung.com/spring-boot-web-service"; - @Autowired - private ProductRepository productRepository; + private final ProductRepository productRepository; + public ProductEndpoint(ProductRepository productRepository) { + this.productRepository = productRepository; + } @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getProductRequest") @ResponsePayload diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java index d04302456b..f6b48af278 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java @@ -1,11 +1,11 @@ package com.baeldung.webservice.generated; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; /** @@ -13,17 +13,17 @@ import javax.xml.bind.annotation.XmlType; * *

The following schema fragment specifies the expected content contained within this class. * - *

- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
+ *
{@code
+ * 
+ *   
+ *     
+ *       
+ *         
+ *       
+ *     
+ *   
+ * 
+ * }
* * */ diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java index f8fcaa094f..a2360d83eb 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java @@ -1,11 +1,11 @@ package com.baeldung.webservice.generated; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; /** @@ -13,17 +13,17 @@ import javax.xml.bind.annotation.XmlType; * *

The following schema fragment specifies the expected content contained within this class. * - *

- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="product" type="{http://baeldung.com/spring-boot-web-service}product"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
+ *
{@code
+ * 
+ *   
+ *     
+ *       
+ *         
+ *       
+ *     
+ *   
+ * 
+ * }
* * */ diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java index 015ecc3f0a..e5877dd20b 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java @@ -1,7 +1,7 @@ package com.baeldung.webservice.generated; -import javax.xml.bind.annotation.XmlRegistry; +import jakarta.xml.bind.annotation.XmlRegistry; /** @@ -32,6 +32,8 @@ public class ObjectFactory { /** * Create an instance of {@link GetProductRequest } * + * @return + * the new instance of {@link GetProductRequest } */ public GetProductRequest createGetProductRequest() { return new GetProductRequest(); @@ -40,6 +42,8 @@ public class ObjectFactory { /** * Create an instance of {@link GetProductResponse } * + * @return + * the new instance of {@link GetProductResponse } */ public GetProductResponse createGetProductResponse() { return new GetProductResponse(); @@ -48,6 +52,8 @@ public class ObjectFactory { /** * Create an instance of {@link Product } * + * @return + * the new instance of {@link Product } */ public Product createProduct() { return new Product(); diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java index 5957aa44b4..f1d62d1489 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java @@ -1,10 +1,10 @@ package com.baeldung.webservice.generated; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlType; /** @@ -12,18 +12,18 @@ import javax.xml.bind.annotation.XmlType; * *

The following schema fragment specifies the expected content contained within this class. * - *

- * <complexType name="product">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
+ *
{@code
+ * 
+ *   
+ *     
+ *       
+ *         
+ *         
+ *       
+ *     
+ *   
+ * 
+ * }
* * */ diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java index 298ae9374b..fa8f2aeec5 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java @@ -1,2 +1,2 @@ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://baeldung.com/spring-boot-web-service", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://baeldung.com/spring-boot-web-service", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) package com.baeldung.webservice.generated; diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/keycloaktestcontainers/KeycloakTestContainers.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/keycloaktestcontainers/KeycloakTestContainers.java index 2a50a646c5..d68fae9cb5 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/keycloaktestcontainers/KeycloakTestContainers.java +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/keycloaktestcontainers/KeycloakTestContainers.java @@ -4,8 +4,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; -import javax.annotation.PostConstruct; - import org.apache.http.client.utils.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +21,7 @@ import org.springframework.web.reactive.function.client.WebClient; import dasniko.testcontainers.keycloak.KeycloakContainer; import io.restassured.RestAssured; +import jakarta.annotation.PostConstruct; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public abstract class KeycloakTestContainers { diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java index edd15090b8..0d58cfde17 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.core.io.ClassPathResource; import org.springframework.ws.test.server.MockWebServiceClient; import org.springframework.xml.transform.StringSource; @@ -22,6 +23,7 @@ import org.springframework.xml.transform.StringSource; import com.baeldung.webservice.generated.Product; @WebServiceServerTest +@ComponentScan("com.baeldung.webservice") class ProductEndpointIntegrationTest { private static final Map NAMESPACE_MAPPING = createMapping(); diff --git a/spring-boot-modules/spring-boot-testing/pom.xml b/spring-boot-modules/spring-boot-testing/pom.xml index 7643183fcb..28ce90d8ec 100644 --- a/spring-boot-modules/spring-boot-testing/pom.xml +++ b/spring-boot-modules/spring-boot-testing/pom.xml @@ -50,7 +50,7 @@ - it.ozimov + com.github.codemonstur embedded-redis ${embedded-redis.version} test @@ -114,7 +114,7 @@ 2.2.4 2.4-M1-groovy-4.0 3.0.0 - 0.7.2 + 1.4.2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/TestRedisConfiguration.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/TestRedisConfiguration.java index 10e5d56857..f0ac4be194 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/TestRedisConfiguration.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/TestRedisConfiguration.java @@ -1,18 +1,21 @@ package com.baeldung.boot.embeddedRedis; -import com.baeldung.boot.embeddedRedis.configuration.RedisProperties; +import java.io.IOException; + import org.springframework.boot.test.context.TestConfiguration; -import redis.embedded.RedisServer; + +import com.baeldung.boot.embeddedRedis.configuration.RedisProperties; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; +import redis.embedded.RedisServer; @TestConfiguration public class TestRedisConfiguration { private final RedisServer redisServer; - public TestRedisConfiguration(final RedisProperties redisProperties) { + public TestRedisConfiguration(final RedisProperties redisProperties) throws IOException { this.redisServer = new RedisServer(redisProperties.getRedisPort()); //Uncomment below if running on windows and can't start redis server // this.redisServer = RedisServer.builder().setting("maxheap 200m").port(6379).setting("bind localhost").build(); @@ -20,12 +23,12 @@ public class TestRedisConfiguration { } @PostConstruct - public void postConstruct() { + public void postConstruct() throws IOException { redisServer.start(); } @PreDestroy - public void preDestroy() { + public void preDestroy() throws IOException { redisServer.stop(); } } diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/domain/repository/UserRepositoryIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/domain/repository/UserRepositoryIntegrationTest.java index 9577ccf0e8..331801cc0a 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/domain/repository/UserRepositoryIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/embeddedRedis/domain/repository/UserRepositoryIntegrationTest.java @@ -1,26 +1,25 @@ package com.baeldung.boot.embeddedRedis.domain.repository; -import com.baeldung.boot.embeddedRedis.TestRedisConfiguration; -import com.baeldung.boot.embeddedRedis.domain.User; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.UUID; -import static org.junit.Assert.assertNotNull; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import com.baeldung.boot.embeddedRedis.TestRedisConfiguration; +import com.baeldung.boot.embeddedRedis.domain.User; + -@RunWith(SpringRunner.class) @SpringBootTest(classes = TestRedisConfiguration.class) -public class UserRepositoryIntegrationTest { +class UserRepositoryIntegrationTest { @Autowired private UserRepository userRepository; @Test - public void shouldSaveUser_toRedis() { + void shouldSaveUser_toRedis() { final UUID id = UUID.randomUUID(); final User user = new User(id, "name"); diff --git a/spring-boot-modules/spring-caching-3/README.md b/spring-boot-modules/spring-caching-3/README.md new file mode 100644 index 0000000000..5429a0bb2f --- /dev/null +++ b/spring-boot-modules/spring-caching-3/README.md @@ -0,0 +1,2 @@ +## Relevant articles + diff --git a/spring-boot-modules/spring-caching-3/pom.xml b/spring-boot-modules/spring-caching-3/pom.xml new file mode 100644 index 0000000000..dcdf886502 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + spring-caching-3 + 0.1-SNAPSHOT + spring-caching-3 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + jar + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookRepository.java b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookRepository.java new file mode 100644 index 0000000000..07898aa090 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.caching.disable; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BookRepository extends JpaRepository { + + List findByIsbn(String isbn); +} diff --git a/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReview.java b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReview.java new file mode 100644 index 0000000000..210cdb0d8a --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReview.java @@ -0,0 +1,70 @@ +package com.baeldung.caching.disable; + +import jakarta.persistence.*; + +import java.util.Objects; + +@Entity +@Table(name = "BOOK_REVIEWS") +public class BookReview { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_reviews_reviews_id_seq") + @SequenceGenerator(name = "book_reviews_reviews_id_seq", sequenceName = "book_reviews_reviews_id_seq", allocationSize = 1) + private Long reviewsId; + private String userId; + private String isbn; + private String bookRating; + + public Long getReviewsId() { + return reviewsId; + } + + public void setReviewsId(Long reviewsId) { + this.reviewsId = reviewsId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public String getBookRating() { + return bookRating; + } + + public void setBookRating(String bookRating) { + this.bookRating = bookRating; + } + + @Override + public String toString() { + return "BookReview{" + "reviewsId=" + reviewsId + ", userId='" + userId + '\'' + ", isbn='" + isbn + '\'' + ", bookRating='" + bookRating + '\'' + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + BookReview that = (BookReview) o; + return Objects.equals(reviewsId, that.reviewsId) && Objects.equals(userId, that.userId) && Objects.equals(isbn, that.isbn) && Objects.equals(bookRating, that.bookRating); + } + + @Override + public int hashCode() { + return Objects.hash(reviewsId, userId, isbn, bookRating); + } +} diff --git a/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewApplication.java b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewApplication.java new file mode 100644 index 0000000000..c035424632 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.caching.disable; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; + +@SpringBootApplication +@EnableCaching +@EnableAutoConfiguration +public class BookReviewApplication { + public static void main(String[] args) { + SpringApplication.run(BookReviewApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewsLogic.java b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewsLogic.java new file mode 100644 index 0000000000..1af8cdf4ab --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/BookReviewsLogic.java @@ -0,0 +1,25 @@ +package com.baeldung.caching.disable; + +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class BookReviewsLogic { + + @Autowired + private BookRepository bookRepository; + + @Autowired + private CacheManager cacheManager; + + @Cacheable(value = "book_reviews", key = "#isbn") + public List getBooksByIsbn(String isbn) { + return bookRepository.findByIsbn(isbn); + } +} diff --git a/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/CacheConfig.java b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/CacheConfig.java new file mode 100644 index 0000000000..23f90370f5 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/java/com/baeldung/caching/disable/CacheConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.caching.disable; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.cache.support.NoOpCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public CacheManager cacheManager(@Value("${appconfig.cache.enabled}") String isCacheEnabled) { + if (isCacheEnabled.equalsIgnoreCase("false")) { + return new NoOpCacheManager(); + } + + return new ConcurrentMapCacheManager(); + } +} diff --git a/spring-boot-modules/spring-caching-3/src/main/resources/application.properties b/spring-boot-modules/spring-caching-3/src/main/resources/application.properties new file mode 100644 index 0000000000..f3c5e31283 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +# Enabling H2 Console +spring.h2.console.enabled=true +spring.h2.console.path=/h2 +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true diff --git a/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicCacheDisabledUnitTest.java b/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicCacheDisabledUnitTest.java new file mode 100644 index 0000000000..34f1052363 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicCacheDisabledUnitTest.java @@ -0,0 +1,68 @@ +package com.baeldung.caching.disable; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.test.context.TestPropertySource; + +@SpringBootTest(classes = BookReviewApplication.class) +@ExtendWith(OutputCaptureExtension.class) +@TestPropertySource(properties = { + "appconfig.cache.enabled=false" +}) +public class BookReviewsLogicCacheDisabledUnitTest { + + @Autowired + private BookReviewsLogic bookReviewsLogic; + + @Autowired + private BookRepository bookRepository; + + @Test + public void givenCacheDisabled_whenLogicExecuted2ndTime_thenItQueriesDB(CapturedOutput output){ + BookReview bookReview = insertBookReview(); + + bookReviewsLogic.getBooksByIsbn(bookReview.getIsbn()); + + String target = "Hibernate: select b1_0.reviews_id," + + "b1_0.book_rating,b1_0.isbn,b1_0.user_id " + + "from book_reviews b1_0 " + + "where b1_0.isbn=?"; + + String[] logs = output.toString() + .split("\\r?\\n"); + assertThat(logs).anyMatch(e -> e.contains(target)); + + bookReviewsLogic.getBooksByIsbn(bookReview.getIsbn()); + logs = output.toString() + .split("\\r?\\n"); + + long count = Arrays.stream(logs) + .filter(e -> e.contains(target)) + .count(); + + // count 2 means the select query log from 1st and 2nd execution. + assertEquals(2, count); + } + + private BookReview insertBookReview() { + BookReview bookReview = new BookReview(); + bookReview.setReviewsId(123L); + bookReview.setBookRating("3.2"); + bookReview.setUserId("111"); + bookReview.setIsbn("1234"); + bookRepository.save(bookReview); + return bookReview; + } +} diff --git a/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicUnitTest.java b/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicUnitTest.java new file mode 100644 index 0000000000..8b1b2faa49 --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/test/java/com/baeldung/caching/disable/BookReviewsLogicUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.caching.disable; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.test.context.TestPropertySource; + +@SpringBootTest(classes = BookReviewApplication.class) +@ExtendWith(OutputCaptureExtension.class) +public class BookReviewsLogicUnitTest { + + @Autowired + private BookReviewsLogic bookReviewsLogic; + + @Autowired + private BookRepository bookRepository; + + @Test + public void givenCacheEnabled_whenLogicExecuted2ndTime_thenItDoesntQueriesDB(CapturedOutput output){ + BookReview bookReview = insertBookReview(); + + String target = "Hibernate: select b1_0.reviews_id," + + "b1_0.book_rating,b1_0.isbn,b1_0.user_id " + + "from book_reviews b1_0 " + + "where b1_0.isbn=?"; + + // 1st execution + bookReviewsLogic.getBooksByIsbn(bookReview.getIsbn()); + String[] logs = output.toString() + .split("\\r?\\n"); + assertThat(logs).anyMatch(e -> e.contains(target)); + + // 2nd execution + bookReviewsLogic.getBooksByIsbn(bookReview.getIsbn()); + logs = output.toString() + .split("\\r?\\n"); + System.out.println(logs); + long count = Arrays.stream(logs) + .filter(e -> e.equals(target)) + .count(); + + // count 1 means the select query log from 1st execution. + assertEquals(1,count); + } + + private BookReview insertBookReview() { + BookReview bookReview = new BookReview(); + bookReview.setReviewsId(123L); + bookReview.setBookRating("3.2"); + bookReview.setUserId("111"); + bookReview.setIsbn("1234"); + bookRepository.save(bookReview); + return bookReview; + } +} diff --git a/spring-boot-modules/spring-caching-3/src/test/resources/application.properties b/spring-boot-modules/spring-caching-3/src/test/resources/application.properties new file mode 100644 index 0000000000..c62237927f --- /dev/null +++ b/spring-boot-modules/spring-caching-3/src/test/resources/application.properties @@ -0,0 +1,12 @@ +appconfig.cache.enabled=true +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +# Enabling H2 Console +spring.h2.console.enabled=true +spring.h2.console.path=/h2 +spring.jpa.hibernate.ddl-auto=update +server.port=8000 +spring.jpa.show-sql=true \ No newline at end of file diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 2fd05ef394..4092c68080 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -35,6 +35,7 @@ org.springframework spring-oxm + ${spring-oxm.version} com.thoughtworks.xstream @@ -165,5 +166,6 @@ 3.2.0 3.3.0 4.0.1 + 6.1.4 diff --git a/spring-cloud-modules/pom.xml b/spring-cloud-modules/pom.xml index 2613b9f9ce..187958fa6c 100644 --- a/spring-cloud-modules/pom.xml +++ b/spring-cloud-modules/pom.xml @@ -22,7 +22,8 @@ spring-cloud-hystrix - spring-cloud-bootstrap + + spring-cloud-ribbon-client spring-cloud-zookeeper spring-cloud-gateway diff --git a/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml index c1be447822..4831759fef 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../../parent-boot-2 + ../../../parent-boot-3 @@ -42,7 +42,7 @@ - 2021.0.7 + 2022.0.4 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/customer-service/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/customer-service/pom.xml index da2dee97d5..c4d31138ad 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/customer-service/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/customer-service/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../../parent-boot-2 + ../../../parent-boot-3 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml index 28c1a741a6..0527a232f7 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../../parent-boot-2 + ../../../parent-boot-3 @@ -54,7 +54,7 @@ - 2021.0.7 + 2022.0.3 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java index fa389ec6a3..b30515cdcf 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java @@ -4,41 +4,38 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; @Configuration @EnableWebSecurity @Order(1) -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("discUser").password("{noop}discPassword").roles("SYSTEM"); } - @Override protected void configure(HttpSecurity http) throws Exception { - http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS).and().requestMatchers().antMatchers("/eureka/**").and().authorizeRequests().antMatchers("/eureka/**").hasRole("SYSTEM").anyRequest().denyAll().and().httpBasic().and().csrf() - .disable(); + http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)).authorizeHttpRequests(auth -> auth.requestMatchers("/eureka/**")).authorizeRequests(auth -> auth.requestMatchers("/eureka/**").hasRole("SYSTEM").anyRequest().denyAll()).httpBasic( + Customizer.withDefaults()).csrf(csrf -> csrf.disable()); } @Configuration // no order tag means this is the last security filter to be evaluated - public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter { + public static class AdminSecurityConfig { - @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } - @Override protected void configure(HttpSecurity http) throws Exception { - http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER).and().httpBasic().disable().authorizeRequests().antMatchers(HttpMethod.GET, "/").hasRole("ADMIN").antMatchers("/info", "/health").authenticated().anyRequest().denyAll() - .and().csrf().disable(); + http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.NEVER)).httpBasic(basic -> basic.disable()).authorizeRequests().requestMatchers(HttpMethod.GET, "/").hasRole("ADMIN").requestMatchers("/info", "/health").authenticated().anyRequest().denyAll() + .and().csrf(csrf -> csrf.disable()); } } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml index fa6735199f..b29d2eb760 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../../parent-boot-2 + ../../../parent-boot-3 @@ -55,18 +55,16 @@ org.springframework.boot spring-boot-starter-data-redis - - org.springframework.cloud - spring-cloud-starter-sleuth - - - org.springframework.cloud - spring-cloud-sleuth-zipkin - org.springframework.cloud spring-cloud-starter-openfeign + + io.rest-assured + rest-assured + ${rest-assured.version} + test + @@ -105,7 +103,8 @@ - 2021.0.7 + 2022.0.4 + 5.4.0 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/inline.bundle.js.map b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/inline.bundle.js.map deleted file mode 100644 index 7163a5f96e..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/inline.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap 201a3a25457ab722584e"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,YAAI;AACJ;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,mDAA2C,cAAc;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId])\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length)\n \t\t\tresolves.shift()();\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t4: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tif(installedChunks[chunkId] === 0)\n \t\t\treturn Promise.resolve();\n\n \t\t// an Promise means \"currently loading\".\n \t\tif(installedChunks[chunkId]) {\n \t\t\treturn installedChunks[chunkId][2];\n \t\t}\n \t\t// start chunk loading\n \t\tvar head = document.getElementsByTagName('head')[0];\n \t\tvar script = document.createElement('script');\n \t\tscript.type = 'text/javascript';\n \t\tscript.charset = 'utf-8';\n \t\tscript.async = true;\n \t\tscript.timeout = 120000;\n\n \t\tif (__webpack_require__.nc) {\n \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t}\n \t\tscript.src = __webpack_require__.p + \"\" + chunkId + \".chunk.js\";\n \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n \t\tscript.onerror = script.onload = onScriptComplete;\n \t\tfunction onScriptComplete() {\n \t\t\t// avoid mem leaks in IE.\n \t\t\tscript.onerror = script.onload = null;\n \t\t\tclearTimeout(timeout);\n \t\t\tvar chunk = installedChunks[chunkId];\n \t\t\tif(chunk !== 0) {\n \t\t\t\tif(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n \t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t}\n \t\t};\n\n \t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\tinstalledChunks[chunkId] = [resolve, reject];\n \t\t});\n \t\tinstalledChunks[chunkId][2] = promise;\n\n \t\thead.appendChild(script);\n \t\treturn promise;\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 201a3a25457ab722584e"],"sourceRoot":""} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/main.bundle.js.map b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/main.bundle.js.map deleted file mode 100644 index 676177396e..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/main.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/app/app.component.css","webpack:///./src/app/book/book-detail/book-detail.component.css","webpack:///./src/app/book/book-list/book-list.component.css","webpack:///./src/app/rating/rating.component.css","webpack:///./src/app/app.component.html","webpack:///./src/app/book/book-detail/book-detail.component.html","webpack:///./src/app/book/book-list/book-list.component.html","webpack:///./src/app/rating/rating.component.html","webpack:///./src/app/http.service.ts","webpack:///./src/app/principal.ts","webpack:///./src/app/book.ts","webpack:///./src async","webpack:///./src/main.ts","webpack:///./src/app/app.component.ts","webpack:///./src/app/app.module.ts","webpack:///./src/app/book/book-detail/book-detail.component.ts","webpack:///./src/app/book/book-list/book-list.component.ts","webpack:///./src/app/click-stop-propagation.directive.ts","webpack:///./src/app/rating.ts","webpack:///./src/app/rating/rating.component.ts","webpack:///./src/environments/environment.ts"],"names":[],"mappings":";;;;;AAAA;AACA;;;AAGA;AACA,wCAAyC,kBAAkB,KAAK;;AAEhE;;;AAGA;AACA,2C;;;;;;;ACXA;AACA;;;AAGA;AACA;;AAEA;;;AAGA;AACA,2C;;;;;;;ACXA;AACA;;;AAGA;AACA,wCAAyC,kBAAkB,KAAK;;AAEhE;;;AAGA;AACA,2C;;;;;;;ACXA;AACA;;;AAGA;AACA,uCAAwC,sBAAsB,KAAK,uBAAuB,yBAAyB,KAAK,mBAAmB,yBAAyB,KAAK;;AAEzK;;;AAGA;AACA,2C;;;;;;;ACXA,ywD;;;;;;;ACAA,qNAAqN,kEAAkE,oBAAoB,mEAAmE,qBAAqB,wN;;;;;;;ACAnY,sEAAsE,eAAe,kJAAkJ,+bAA+b,YAAY,uEAAuE,aAAa,2qCAA2qC,kvC;;;;;;;ACAj7D,kEAAkE,eAAe,8FAA8F,uFAAuF,scAAsc,sLAAsL,eAAe,0KAA0K,MAAM,4e;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAxhC;AAE6B;AAKtE,IAAa,WAAW;IAEtB,qBAAoB,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAI,CAAC;IAEnC,wBAAE,GAAF;QACE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACjD,CAAC;IAED,4BAAM,GAAN;QACE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1D,CAAC;IAED,8BAAQ,GAAR;QACE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACjE,CAAC;IAED,gCAAU,GAAV,UAAW,OAAa;QACtB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,GAAG,OAAO,CAAC,EAAE,EAAE,OAAO,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACzF,CAAC;IAED,gCAAU,GAAV,UAAW,IAAU;QACnB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC,EAAE,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChF,CAAC;IAED,gCAAU,GAAV,UAAW,OAAa;QACtB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,OAAO,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5E,CAAC;IAED,gCAAU,GAAV,UAAW,MAAc;QACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iCAAiC,GAAG,MAAM,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACvF,CAAC;IAED,kCAAY,GAAZ,UAAa,MAAc;QACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,MAAM,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC/E,CAAC;IAED,kCAAY,GAAZ,UAAa,QAAgB;QAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,0BAA0B,GAAG,QAAQ,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrF,CAAC;IAED,kCAAY,GAAZ,UAAa,MAAc;QACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,0BAA0B,GAAG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3F,CAAC;IAEO,iCAAW,GAAnB;QACE,IAAI,OAAO,GAAG,IAAI,8DAAO,CAAC,EAAC,cAAc,EAAE,kBAAkB,EAAC,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,qEAAc,CAAC,EAAC,OAAO,EAAE,OAAO,EAAC,CAAC,CAAC;IAChD,CAAC;IACH,kBAAC;AAAD,CAAC;AAhDY,WAAW;IADvB,wFAAU,EAAE;yDAGe,2DAAI,oBAAJ,2DAAI;GAFnB,WAAW,CAgDvB;AAhDuB;;;;;;;;;;;ACPxB;AAAA;IAIE,mBAAY,aAAsB,EAAE,WAAkB;QAAtD,iBAGC;QALM,gBAAW,GAAgB,EAAE,CAAC;QAGnC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,WAAW,CAAC,GAAG,CAAC,cAAI,IAAI,YAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAApD,CAAoD,CAAC;IAC/E,CAAC;IAED,2BAAO,GAAP;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAC,IAAe,IAAK,WAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAApC,CAAoC,CAAC;IACzF,CAAC;IACH,gBAAC;AAAD,CAAC;;AAED;IAGE,mBAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IACH,gBAAC;AAAD,CAAC;;;;;;;;;;ACpBD;AAAA;IAIE,cAAY,EAAU,EAAE,MAAc,EAAE,KAAa;QACnD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IACH,WAAC;AAAD,CAAC;;;;;;;;;ACTD;AACA;AACA;AACA,uCAAuC,WAAW;AAClD;AACA;AACA;;;;;;;;;;;;;;ACN6C;AAC4B;AAC9B;AACY;AAEvD,EAAE,CAAC,CAAC,8EAAW,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3B,4FAAc,EAAE,CAAC;AACnB,CAAC;AAED,wHAAsB,EAAE,CAAC,eAAe,CAAC,kEAAS,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;ACTZ;AACF;AAGK;AAO3C,IAAa,YAAY;IAKvB,sBAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;QAJ5C,iBAAY,GAAS,IAAI,CAAC;QAC1B,cAAS,GAAc,IAAI,6DAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChD,gBAAW,GAAY,KAAK,CAAC;IAEiB,CAAC;IAE/C,+BAAQ,GAAR;QAAA,iBAQC;QAPC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE;aAClB,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,KAAI,CAAC,SAAS,GAAG,IAAI,6DAAS,CAAC,aAAa,CAAC,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QACzF,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,+BAAQ,GAAR;QAAA,iBAWC;QAVC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;aACtB,SAAS,CAAC,UAAC,QAAkB;YAC5B,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC5B,KAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,KAAI,CAAC,SAAS,GAAG,IAAI,6DAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC1C,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;QACH,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,sCAAe,GAAf;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,iCAAU,GAAV,UAAW,IAAU;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAEH,mBAAC;AAAD,CAAC;AAtCY,YAAY;IALxB,wFAAS,CAAC;QACT,QAAQ,EAAE,UAAU;QACpB,kCAAmC;QACnC,kCAAkC;KACnC,CAAC;yDAMiC,kEAAW,oBAAX,kEAAW;GALjC,YAAY,CAsCxB;AAtCwB;;;;;;;;;;;;;;;;;;;;;;;;;;;ACX+B;AACjB;AACI;AACF;AACI;AACa;AACuB;AACJ;AACN;AAC5B;AAkB3C,IAAa,SAAS;IAAtB;IAAyB,CAAC;IAAD,gBAAC;AAAD,CAAC;AAAb,SAAS;IAhBrB,sFAAQ,CAAC;QACR,YAAY,EAAE;YACZ,oEAAY;YACZ,iFAAe;YACf,wGAA6B;YAC7B,oGAAmB;YACnB,8FAAiB;SAClB;QACD,OAAO,EAAE;YACP,gFAAa;YACb,mEAAW;YACX,iEAAU;SACX;QACD,SAAS,EAAE,CAAC,kEAAW,CAAC;QACxB,SAAS,EAAE,CAAC,oEAAY,CAAC;KAC1B,CAAC;GACW,SAAS,CAAI;AAAJ;;;;;;;;;;;;;;;;;;;;;;AC3BuD;AAC7C;AACU;AAO1C,IAAa,mBAAmB;IAO9B;QALS,iBAAY,GAAS,IAAI,CAAC;QAC1B,cAAS,GAAc,IAAI,CAAC;QAC3B,cAAS,GAAsB,IAAI,mEAAY,EAAO,CAAC;IAGjD,CAAC;IAEjB,sCAAQ,GAAR;IACA,CAAC;IAED,6CAAe,GAAf;QACE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEH,0BAAC;AAAD,CAAC;AAdU;IAAR,mFAAK,EAAE;kDAAe,mDAAI,oBAAJ,mDAAI;yDAAQ;AAC1B;IAAR,mFAAK,EAAE;kDAAY,6DAAS,oBAAT,6DAAS;sDAAQ;AAC3B;IAAT,qFAAM,EAAE;kDAAY,mEAAY,oBAAZ,mEAAY;sDAAgC;AAJtD,mBAAmB;IAL/B,wFAAS,CAAC;QACT,QAAQ,EAAE,iBAAiB;QAC3B,kCAA2C;QAC3C,kCAA0C;KAC3C,CAAC;;GACW,mBAAmB,CAgB/B;AAhB+B;;;;;;;;;;;;;;;;;;;;;;;;ACT6C;AACnC;AACV;AAEe;AAO/C,IAAa,iBAAiB;IAY5B,2BAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;QAVnC,cAAS,GAAc,IAAI,CAAC;QAC3B,mBAAc,GAAuB,IAAI,mEAAY,EAAQ,CAAC;QAExE,UAAK,GAAW,EAAE,CAAC;QACnB,aAAQ,GAAW,EAAE,CAAC;QACtB,YAAO,GAAS,IAAI,mDAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACnE,gBAAW,GAAa,EAAE,CAAC;QAC3B,iBAAY,GAAY,KAAK,CAAC;QAC9B,iBAAY,GAAS,IAAI,CAAC;IAEsB,CAAC;IAEjD,oCAAQ,GAAR;QACE,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,qCAAS,GAAT;QAAA,iBAWC;QAVC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;aACxB,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,SAAS,GAAU,QAAQ,CAAC,IAAI,EAAE;YACtC,SAAS,CAAC,OAAO,CAAC,cAAI;gBACpB,KAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,mDAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC5D,KAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,mDAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACjE,CAAC,CAAC;QACJ,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,0CAAc,GAAd,UAAe,SAAiB;QAC9B,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,sCAAsC;YACvG,uBAAuB;YACvB,IAAI,QAAQ,GAAS,IAAI,mDAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC;YACnH,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAC,CAAC,EAAC,QAAQ,CAAC,CAAC,CAAC,2CAA2C;QACzF,CAAC;IACH,CAAC;IAED,oCAAQ,GAAR,UAAS,SAAiB;QACxB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,oCAAQ,GAAR,UAAS,SAAiB,EAAE,OAAa;QAAzC,iBAiBC;QAhBC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,+BAA+B;QAC/B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;aACjC,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,IAAI,GAAS,IAAI,mDAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YACxE,mCAAmC;YACnC,IAAI,OAAO,GAAS,KAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAC,IAAI,QAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,EAAhB,CAAgB,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7B,KAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,sCAAsC;QACzG,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IAGP,CAAC;IAED,kCAAM,GAAN,UAAO,SAAiB;QAAxB,iBAcC;QAbC,IAAI,IAAI,GAAS,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC;aAC9B,SAAS,CAAC;YACT,EAAE,CAAC,CAAC,KAAI,CAAC,YAAY,KAAK,IAAI,IAAI,KAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,KAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;gBACpF,KAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,KAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAI,CAAC,YAAY,CAAC,CAAC;YAC9C,CAAC;YAED,KAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,gCAAgC;YACjE,KAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,uCAAuC;QAC7E,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,8CAAkB,GAAlB;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,mDAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,sCAAU,GAAV,UAAW,OAAa,EAAE,OAAY;QAAtC,iBAcC;QAbC,sBAAsB;QACtB,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;aACjC,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,IAAI,GAAS,IAAI,mDAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClB,KAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,KAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,KAAI,CAAC,OAAO,GAAG,IAAI,mDAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,yCAAa,GAAb;QACE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAGD,sCAAU,GAAV,UAAW,IAAU;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAEH,wBAAC;AAAD,CAAC;AA5GU;IAAR,mFAAK,EAAE;kDAAY,6DAAS,oBAAT,6DAAS;oDAAQ;AAC3B;IAAT,qFAAM,EAAE;kDAAiB,mEAAY,oBAAZ,mEAAY;yDAAkC;AAH7D,iBAAiB;IAL7B,wFAAS,CAAC;QACT,QAAQ,EAAE,eAAe;QACzB,kCAAyC;QACzC,kCAAwC;KACzC,CAAC;yDAaiC,kEAAW,oBAAX,kEAAW;GAZjC,iBAAiB,CA8G7B;AA9G6B;;;;;;;;;;;;;;;;;;;;;ACXwB;AAKtD,IAAa,6BAA6B;IAA1C;IAOA,CAAC;IAJQ,+CAAO,GAAd,UAAe,KAAU;QAEvB,KAAK,CAAC,eAAe,EAAE,CAAC;IAC1B,CAAC;IACH,oCAAC;AAAD,CAAC;AAJC;IADC,2FAAY,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC;;;;4DAIjC;AANU,6BAA6B;IAHzC,uFAAS,CAAC;QACT,QAAQ,EAAE,2BAA2B;KACtC,CAAC;GACW,6BAA6B,CAOzC;AAPyC;;;;;;;;;ACL1C;AAAA;IAKE,gBAAY,EAAU,EAAE,MAAc,EAAE,KAAa;QACnD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IACH,aAAC;AAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;ACViE;AACjC;AACM;AACK;AAQ5C,IAAa,eAAe;IAQ1B,yBAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;QALnC,cAAS,GAAc,IAAI,CAAC;QACrC,YAAO,GAAa,EAAE,CAAC;QACvB,UAAK,GAAa,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;QAC9B,cAAS,GAAW,IAAI,CAAC;IAEuB,CAAC;IAEjD,kCAAQ,GAAR,cAAY,CAAC;IAEb,qCAAW,GAAX;QACE,IAAI,CAAC,SAAS,GAAG,IAAI,uDAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,mCAAS,GAAT,UAAU,MAAc;QACtB,IAAI,OAAO,GAAW,CAAC,MAAM,CAAC,KAAK,GAAC,CAAC,CAAC,GAAC,GAAG,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC;IAClC,CAAC;IAEO,qCAAW,GAAnB;QAAA,iBAQC;QAPC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;aACrC,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,YAAY,GAAU,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC1C,YAAY,CAAC,OAAO,CAAC,gBAAM,IAAI,YAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,uDAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAArE,CAAqE,CAAC;QACvG,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,sCAAY,GAAZ;QAAA,iBAUC;QATC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,UAAU,GAAW,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC;aACtC,SAAS,CAAC,UAAC,QAAkB;YAC5B,IAAI,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE;YAChC,KAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,uDAAM,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QACnF,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,sCAAY,GAAZ;QAAA,iBAOC;QANC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;aAC1C,SAAS,CAAC;YACT,KAAI,CAAC,SAAS,GAAG,IAAI,uDAAM,CAAC,IAAI,EAAE,KAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,sCAAY,GAAZ,UAAa,MAAc;QACzB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,yCAAe,GAAf;QACE,IAAI,CAAC,SAAS,GAAG,IAAI,uDAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,sCAAY,GAAZ,UAAa,KAAa;QAA1B,iBAYC;QAXC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;aACrC,SAAS,CAAC;YACT,EAAE,CAAC,CAAC,KAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAI,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC3C,KAAI,CAAC,SAAS,GAAG,IAAI,uDAAM,CAAC,IAAI,EAAE,KAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACpD,CAAC;YACD,KAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC,EAAE,UAAC,KAAK;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IAEP,CAAC;IAEH,sBAAC;AAAD,CAAC;AA5EU;IAAR,mFAAK,EAAE;;+CAAgB;AACf;IAAR,mFAAK,EAAE;kDAAY,6DAAS,oBAAT,6DAAS;kDAAQ;AAH1B,eAAe;IAL3B,wFAAS,CAAC;QACT,QAAQ,EAAE,YAAY;QACtB,kCAAsC;QACtC,kCAAqC;KACtC,CAAC;yDASiC,kEAAW,oBAAX,kEAAW;GARjC,eAAe,CA8E3B;AA9E2B;;;;;;;;;;ACX5B;AAAA,mFAAmF;AACnF,8FAA8F;AAC9F,yEAAyE;AACzE,gFAAgF;AAEhF,mFALmF;AAK5E,IAAM,WAAW,GAAG;IACzB,UAAU,EAAE,KAAK;CAClB,CAAC","file":"main.bundle.js","sourcesContent":["exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \".custom-close {\\r\\n float:right;\\r\\n}\\r\\n\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/app.component.css\n// module id = 144\n// module chunks = 1","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \"\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/book/book-detail/book-detail.component.css\n// module id = 145\n// module chunks = 1","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \".custom-close {\\r\\n float:right;\\r\\n}\\r\\n\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/book/book-list/book-list.component.css\n// module id = 146\n// module chunks = 1","exports = module.exports = require(\"../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \"div.progress {\\r\\n margin-top: 5px;\\r\\n}\\r\\n\\r\\n.rating:hover {\\r\\n border: solid blue;\\r\\n}\\r\\n\\r\\n.selected {\\r\\n border: solid blue;\\r\\n}\\r\\n\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/rating/rating.component.css\n// module id = 147\n// module chunks = 1","module.exports = \"\\r\\n\\r\\n
\\r\\n
\\r\\n

Book Rater App

\\r\\n

Anyone can view the books.

\\r\\n

Users can view and create ratings

\\r\\n

Admins can do anything!

\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/app.component.html\n// module id = 149\n// module chunks = 1","module.exports = \"
\\r\\n
\\r\\n \\r\\n

Title: {{selectedBook.title}}

\\r\\n
Author: {{selectedBook.author}}
\\r\\n

A quick summary of the book

\\r\\n \\r\\n
\\r\\n
\\r\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/book/book-detail/book-detail.component.html\n// module id = 150\n// module chunks = 1","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n

Title: {{book.title}}

\\r\\n
Author: {{book.author}}
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n

Add New Book

\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/book/book-list/book-list.component.html\n// module id = 151\n// module chunks = 1","module.exports = \"Ratings:\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/app/rating/rating.component.html\n// module id = 152\n// module chunks = 1","import {Injectable} from \"@angular/core\";\r\nimport {Observable} from \"rxjs\";\r\nimport {Response, Http, Headers, RequestOptions} from \"@angular/http\";\r\nimport {Book} from \"./book\";\r\nimport {Rating} from \"./rating\";\r\n\r\n@Injectable()\r\nexport class HttpService {\r\n\r\n constructor(private http: Http) { }\r\n\r\n me(): Observable {\r\n return this.http.get(\"/me\", this.makeOptions())\r\n }\r\n\r\n logout(): Observable {\r\n return this.http.post(\"/logout\", '', this.makeOptions())\r\n }\r\n\r\n getBooks(): Observable {\r\n return this.http.get(\"/book-service/books\", this.makeOptions())\r\n }\r\n\r\n updateBook(newBook: Book): Observable {\r\n return this.http.put(\"/book-service/books/\" + newBook.id, newBook, this.makeOptions())\r\n }\r\n\r\n deleteBook(book: Book): Observable {\r\n return this.http.delete(\"/book-service/books/\" + book.id, this.makeOptions())\r\n }\r\n\r\n createBook(newBook: Book): Observable {\r\n return this.http.post(\"/book-service/books\", newBook, this.makeOptions())\r\n }\r\n\r\n getRatings(bookId: number): Observable {\r\n return this.http.get(\"/rating-service/ratings?bookId=\" + bookId, this.makeOptions())\r\n }\r\n\r\n createRating(rating: Rating): Observable {\r\n return this.http.post(\"/rating-service/ratings\", rating, this.makeOptions())\r\n }\r\n\r\n deleteRating(ratingId: number) {\r\n return this.http.delete(\"/rating-service/ratings/\" + ratingId, this.makeOptions())\r\n }\r\n\r\n updateRating(rating: Rating) {\r\n return this.http.put(\"/rating-service/ratings/\" + rating.id, rating, this.makeOptions())\r\n }\r\n\r\n private makeOptions(): RequestOptions {\r\n let headers = new Headers({'Content-Type': 'application/json'});\r\n return new RequestOptions({headers: headers});\r\n }\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/http.service.ts","export class Principal {\r\n public authenticated: boolean;\r\n public authorities: Authority[] = [];\r\n\r\n constructor(authenticated: boolean, authorities: any[]) {\r\n this.authenticated = authenticated;\r\n authorities.map(auth => this.authorities.push(new Authority(auth.authority)))\r\n }\r\n\r\n isAdmin() {\r\n return this.authorities.some((auth: Authority) => auth.authority.indexOf('ADMIN') > -1)\r\n }\r\n}\r\n\r\nexport class Authority {\r\n public authority: String;\r\n\r\n constructor(authority: String) {\r\n this.authority = authority;\r\n }\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/principal.ts","export class Book {\r\n id: number;\r\n author: String;\r\n title: String;\r\n constructor(id: number, author: String, title: String){\r\n this.id = id;\r\n this.author = author;\r\n this.title = title;\r\n }\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/book.ts","function webpackEmptyContext(req) {\n\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n}\nwebpackEmptyContext.keys = function() { return []; };\nwebpackEmptyContext.resolve = webpackEmptyContext;\nmodule.exports = webpackEmptyContext;\nwebpackEmptyContext.id = 74;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src async\n// module id = 74\n// module chunks = 1","import {enableProdMode} from \"@angular/core\";\r\nimport {platformBrowserDynamic} from \"@angular/platform-browser-dynamic\";\r\nimport {AppModule} from \"./app/app.module\";\r\nimport {environment} from \"./environments/environment\";\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule);\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/main.ts","import {Component} from \"@angular/core\";\r\nimport {Principal} from \"./principal\";\r\nimport {Response} from \"@angular/http\";\r\nimport {Book} from \"./book\";\r\nimport {HttpService} from \"./http.service\";\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.css']\r\n})\r\nexport class AppComponent {\r\n selectedBook: Book = null;\r\n principal: Principal = new Principal(false, []);\r\n loginFailed: boolean = false;\r\n\r\n constructor(private httpService: HttpService){}\r\n\r\n ngOnInit(): void {\r\n this.httpService.me()\r\n .subscribe((response: Response) => {\r\n let principalJson = response.json();\r\n this.principal = new Principal(principalJson.authenticated, principalJson.authorities);\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n onLogout() {\r\n this.httpService.logout()\r\n .subscribe((response: Response) => {\r\n if (response.status === 200) {\r\n this.loginFailed = false;\r\n this.principal = new Principal(false, []);\r\n window.location.replace(response.url);\r\n }\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n closeBookDetail() {\r\n this.selectedBook = null;\r\n }\r\n\r\n selectBook(book: Book) {\r\n this.selectedBook = book;\r\n }\r\n\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/app.component.ts","import {BrowserModule} from \"@angular/platform-browser\";\r\nimport {NgModule} from \"@angular/core\";\r\nimport {FormsModule} from \"@angular/forms\";\r\nimport {HttpModule} from \"@angular/http\";\r\nimport {AppComponent} from \"./app.component\";\r\nimport {RatingComponent} from \"./rating/rating.component\";\r\nimport {ClickStopPropagationDirective} from \"./click-stop-propagation.directive\";\r\nimport {BookDetailComponent} from \"./book/book-detail/book-detail.component\";\r\nimport {BookListComponent} from \"./book/book-list/book-list.component\";\r\nimport {HttpService} from \"./http.service\";\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n RatingComponent,\r\n ClickStopPropagationDirective,\r\n BookDetailComponent,\r\n BookListComponent\r\n ],\r\n imports: [\r\n BrowserModule,\r\n FormsModule,\r\n HttpModule\r\n ],\r\n providers: [HttpService],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/app.module.ts","import {Component, OnInit, Input, Output, EventEmitter} from \"@angular/core\";\r\nimport {Book} from \"../../book\";\r\nimport {Principal} from \"../../principal\";\r\n\r\n@Component({\r\n selector: 'app-book-detail',\r\n templateUrl: './book-detail.component.html',\r\n styleUrls: ['./book-detail.component.css']\r\n})\r\nexport class BookDetailComponent implements OnInit {\r\n\r\n @Input() selectedBook: Book = null;\r\n @Input() principal: Principal = null;\r\n @Output() closeBook: EventEmitter = new EventEmitter();\r\n\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n closeBookDetail() {\r\n this.closeBook.emit(null);\r\n }\r\n\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/book/book-detail/book-detail.component.ts","import {Component, OnInit, Input, Output, EventEmitter} from \"@angular/core\";\r\nimport {Principal} from \"../../principal\";\r\nimport {Book} from \"../../book\";\r\nimport {Response} from \"@angular/http\";\r\nimport {HttpService} from \"../../http.service\";\r\n\r\n@Component({\r\n selector: 'app-book-list',\r\n templateUrl: './book-list.component.html',\r\n styleUrls: ['./book-list.component.css']\r\n})\r\nexport class BookListComponent implements OnInit {\r\n\r\n @Input() principal: Principal = null;\r\n @Output() onBookSelected: EventEmitter = new EventEmitter();\r\n\r\n books: Book[] = [];\r\n newBooks: Book[] = [];\r\n newBook: Book = new Book(Math.floor(Math.random() * 1000), '', '');\r\n booksToEdit: number[] = [];\r\n isAddNewBook: boolean = false;\r\n selectedBook: Book = null;\r\n\r\n constructor(private httpService: HttpService) { }\r\n\r\n ngOnInit() {\r\n this.loadBooks();\r\n }\r\n\r\n loadBooks() {\r\n this.httpService.getBooks()\r\n .subscribe((response: Response) => {\r\n let booksJson: any[] = response.json()\r\n booksJson.forEach(book => {\r\n this.books.push(new Book(book.id, book.author, book.title));\r\n this.newBooks.push(new Book(book.id, book.author, book.title));\r\n })\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n cancelEditBook(bookIndex: number) {\r\n if (this.booksToEdit.indexOf(bookIndex) !== -1) {\r\n this.booksToEdit.splice(this.booksToEdit.indexOf(bookIndex), 1); //remove the index of the book to edit\r\n //get the original book\r\n let bookCopy: Book = new Book(this.books[bookIndex].id, this.books[bookIndex].author, this.books[bookIndex].title);\r\n this.newBooks.splice(bookIndex,1,bookCopy); //replace the edited book with the old book\r\n }\r\n }\r\n\r\n editBook(bookIndex: number) {\r\n this.booksToEdit.push(bookIndex);\r\n }\r\n\r\n saveBook(bookIndex: number, newBook: Book) {\r\n console.log(newBook);\r\n //save the book to the database\r\n this.httpService.updateBook(newBook)\r\n .subscribe((response: Response) => {\r\n let bookJson = response.json();\r\n let book: Book = new Book(bookJson.id, bookJson.author, bookJson.title);\r\n //update the current array of books\r\n let bookArr: Book = this.books.find(b => b.id === book.id);\r\n bookArr.title = book.title;\r\n bookArr.author = book.author;\r\n this.booksToEdit.splice(this.booksToEdit.indexOf(bookIndex), 1); //remove the index of the book to edit\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n\r\n\r\n }\r\n\r\n delete(bookIndex: number) {\r\n let book: Book = this.books[bookIndex];\r\n this.httpService.deleteBook(book)\r\n .subscribe(() => {\r\n if (this.selectedBook !== null && this.books[bookIndex].id === this.selectedBook.id) {\r\n this.selectedBook = null;\r\n this.onBookSelected.emit(this.selectedBook);\r\n }\r\n\r\n this.books.splice(bookIndex, 1); //remove the book at this index;\r\n this.newBooks.splice(bookIndex, 1); //remove the editing book at this index\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n activateAddNewBook() {\r\n this.isAddNewBook = true;\r\n this.newBook = new Book(null, '', '');\r\n }\r\n\r\n addNewBook(newBook: Book, element: any) {\r\n //write new book to db\r\n this.httpService.createBook(newBook)\r\n .subscribe((response: Response) => {\r\n let bookJson = response.json();\r\n let book: Book = new Book(bookJson.id, bookJson.author, bookJson.title);\r\n console.log(book);\r\n this.books.push(book);\r\n this.newBooks.push(book);\r\n this.newBook = new Book(Math.floor(Math.random() * 1000), '', '');\r\n element.focus();\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n cancelAddBook() {\r\n this.isAddNewBook = false;\r\n }\r\n\r\n\r\n selectBook(book: Book) {\r\n this.selectedBook = book;\r\n this.onBookSelected.emit(book);\r\n }\r\n\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/book/book-list/book-list.component.ts","import {Directive, HostListener} from \"@angular/core\";\r\n\r\n@Directive({\r\n selector: '[appClickStopPropagation]'\r\n})\r\nexport class ClickStopPropagationDirective\r\n{\r\n @HostListener(\"click\", [\"$event\"])\r\n public onClick(event: any): void\r\n {\r\n event.stopPropagation();\r\n }\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/click-stop-propagation.directive.ts","export class Rating{\r\n id: number;\r\n bookId: number;\r\n stars: number;\r\n\r\n constructor(id: number, bookId: number, stars: number) {\r\n this.id = id;\r\n this.bookId = bookId;\r\n this.stars = stars;\r\n }\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/rating.ts","import {Component, OnInit, Input, OnChanges} from \"@angular/core\";\r\nimport {Rating} from \"../rating\";\r\nimport {Principal} from \"../principal\";\r\nimport {HttpService} from \"../http.service\";\r\nimport {Response} from \"@angular/http\";\r\n\r\n@Component({\r\n selector: 'app-rating',\r\n templateUrl: './rating.component.html',\r\n styleUrls: ['./rating.component.css']\r\n})\r\nexport class RatingComponent implements OnInit, OnChanges {\r\n\r\n @Input() bookId: number;\r\n @Input() principal: Principal = null;\r\n ratings: Rating[] = [];\r\n stars: number[] = [1,2,3,4,5];\r\n newRating: Rating = null;\r\n\r\n constructor(private httpService: HttpService) { }\r\n\r\n ngOnInit() {}\r\n\r\n ngOnChanges() {\r\n this.newRating = new Rating(null, this.bookId, 1);\r\n this.ratings = [];\r\n this.loadRatings();\r\n }\r\n\r\n findWidth(rating: Rating): String {\r\n let percent: number = (rating.stars/5)*100;\r\n return percent.toString() + '%';\r\n }\r\n\r\n private loadRatings() {\r\n this.httpService.getRatings(this.bookId)\r\n .subscribe((response: Response) => {\r\n let responseJson: any[] = response.json();\r\n responseJson.forEach(rating => this.ratings.push(new Rating(rating.id, rating.bookId, rating.stars)))\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n onSaveRating() {\r\n console.log(this.newRating);\r\n let ratingCopy: Rating = Object.assign({}, this.newRating);\r\n this.httpService.createRating(ratingCopy)\r\n .subscribe((response: Response) => {\r\n let ratingJson = response.json()\r\n this.ratings.push(new Rating(ratingJson.id, ratingJson.bookId, ratingJson.stars))\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n updateRating() {\r\n this.httpService.updateRating(this.newRating)\r\n .subscribe(() => {\r\n this.newRating = new Rating(null, this.bookId, 1);\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n }\r\n\r\n selectRating(rating: Rating) {\r\n if (this.principal.isAdmin()) {\r\n this.newRating = rating;\r\n }\r\n }\r\n\r\n cancelSelection() {\r\n this.newRating = new Rating(null, this.bookId, 1);\r\n }\r\n\r\n deleteRating(index: number) {\r\n let rating = this.ratings[index];\r\n this.httpService.deleteRating(rating.id)\r\n .subscribe(() => {\r\n if (this.ratings[index] === this.newRating) {\r\n this.newRating = new Rating(null, this.bookId, 1);\r\n }\r\n this.ratings.splice(index, 1);\r\n }, (error) => {\r\n console.log(error);\r\n });\r\n\r\n }\r\n\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/app/rating/rating.component.ts","// The file contents for the current environment will overwrite these during build.\r\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\r\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\r\n// The list of which env maps to which file can be found in `.angular-cli.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/environments/environment.ts"],"sourceRoot":""} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/polyfills.bundle.js.map b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/polyfills.bundle.js.map deleted file mode 100644 index 4304ec0970..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/polyfills.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./~/core-js/modules/_an-object.js","webpack:///./~/core-js/modules/_export.js","webpack:///./~/core-js/modules/_is-object.js","webpack:///./~/core-js/modules/_global.js","webpack:///./~/core-js/modules/_has.js","webpack:///./~/core-js/modules/_metadata.js","webpack:///./~/core-js/modules/_wks.js","webpack:///./~/core-js/modules/_fails.js","webpack:///./~/core-js/modules/_object-dp.js","webpack:///./~/core-js/modules/_descriptors.js","webpack:///./~/core-js/modules/_object-gpo.js","webpack:///./~/core-js/modules/_a-function.js","webpack:///./~/core-js/modules/_core.js","webpack:///./~/core-js/modules/_ctx.js","webpack:///./~/core-js/modules/_object-gopd.js","webpack:///./~/core-js/modules/_redefine.js","webpack:///./~/core-js/modules/_for-of.js","webpack:///./~/core-js/modules/_hide.js","webpack:///./~/core-js/modules/_meta.js","webpack:///./~/core-js/modules/_property-desc.js","webpack:///./~/core-js/modules/_uid.js","webpack:///(webpack)/buildin/global.js","webpack:///./~/core-js/modules/_an-instance.js","webpack:///./~/core-js/modules/_cof.js","webpack:///./~/core-js/modules/_collection.js","webpack:///./~/core-js/modules/_defined.js","webpack:///./~/core-js/modules/_enum-bug-keys.js","webpack:///./~/core-js/modules/_iobject.js","webpack:///./~/core-js/modules/_iterators.js","webpack:///./~/core-js/modules/_object-create.js","webpack:///./~/core-js/modules/_redefine-all.js","webpack:///./~/core-js/modules/_set-to-string-tag.js","webpack:///./~/core-js/modules/_shared-key.js","webpack:///./~/core-js/modules/_shared.js","webpack:///./~/core-js/modules/_to-iobject.js","webpack:///./~/core-js/modules/_to-length.js","webpack:///./~/core-js/modules/_to-object.js","webpack:///./~/core-js/modules/_to-primitive.js","webpack:///./~/core-js/modules/_array-methods.js","webpack:///./~/core-js/modules/_collection-strong.js","webpack:///./~/core-js/modules/_dom-create.js","webpack:///./~/core-js/modules/_ie8-dom-define.js","webpack:///./~/core-js/modules/_iter-create.js","webpack:///./~/core-js/modules/_object-gops.js","webpack:///./~/core-js/modules/_object-keys-internal.js","webpack:///./~/core-js/modules/_object-keys.js","webpack:///./~/core-js/modules/_object-pie.js","webpack:///./~/core-js/modules/_set-proto.js","webpack:///./~/core-js/modules/_to-integer.js","webpack:///./src/polyfills.ts","webpack:///./~/core-js/es6/reflect.js","webpack:///./~/core-js/es7/reflect.js","webpack:///./~/core-js/modules/_array-from-iterable.js","webpack:///./~/core-js/modules/_array-includes.js","webpack:///./~/core-js/modules/_array-species-constructor.js","webpack:///./~/core-js/modules/_array-species-create.js","webpack:///./~/core-js/modules/_bind.js","webpack:///./~/core-js/modules/_classof.js","webpack:///./~/core-js/modules/_collection-weak.js","webpack:///./~/core-js/modules/_html.js","webpack:///./~/core-js/modules/_inherit-if-required.js","webpack:///./~/core-js/modules/_invoke.js","webpack:///./~/core-js/modules/_is-array-iter.js","webpack:///./~/core-js/modules/_is-array.js","webpack:///./~/core-js/modules/_iter-call.js","webpack:///./~/core-js/modules/_iter-define.js","webpack:///./~/core-js/modules/_iter-detect.js","webpack:///./~/core-js/modules/_iter-step.js","webpack:///./~/core-js/modules/_library.js","webpack:///./~/core-js/modules/_object-assign.js","webpack:///./~/core-js/modules/_object-dps.js","webpack:///./~/core-js/modules/_object-gopn.js","webpack:///./~/core-js/modules/_own-keys.js","webpack:///./~/core-js/modules/_set-species.js","webpack:///./~/core-js/modules/_to-index.js","webpack:///./~/core-js/modules/core.get-iterator-method.js","webpack:///./~/core-js/modules/es6.map.js","webpack:///./~/core-js/modules/es6.reflect.apply.js","webpack:///./~/core-js/modules/es6.reflect.construct.js","webpack:///./~/core-js/modules/es6.reflect.define-property.js","webpack:///./~/core-js/modules/es6.reflect.delete-property.js","webpack:///./~/core-js/modules/es6.reflect.enumerate.js","webpack:///./~/core-js/modules/es6.reflect.get-own-property-descriptor.js","webpack:///./~/core-js/modules/es6.reflect.get-prototype-of.js","webpack:///./~/core-js/modules/es6.reflect.get.js","webpack:///./~/core-js/modules/es6.reflect.has.js","webpack:///./~/core-js/modules/es6.reflect.is-extensible.js","webpack:///./~/core-js/modules/es6.reflect.own-keys.js","webpack:///./~/core-js/modules/es6.reflect.prevent-extensions.js","webpack:///./~/core-js/modules/es6.reflect.set-prototype-of.js","webpack:///./~/core-js/modules/es6.reflect.set.js","webpack:///./~/core-js/modules/es6.set.js","webpack:///./~/core-js/modules/es6.weak-map.js","webpack:///./~/core-js/modules/es7.reflect.define-metadata.js","webpack:///./~/core-js/modules/es7.reflect.delete-metadata.js","webpack:///./~/core-js/modules/es7.reflect.get-metadata-keys.js","webpack:///./~/core-js/modules/es7.reflect.get-metadata.js","webpack:///./~/core-js/modules/es7.reflect.get-own-metadata-keys.js","webpack:///./~/core-js/modules/es7.reflect.get-own-metadata.js","webpack:///./~/core-js/modules/es7.reflect.has-metadata.js","webpack:///./~/core-js/modules/es7.reflect.has-own-metadata.js","webpack:///./~/core-js/modules/es7.reflect.metadata.js","webpack:///./~/process/browser.js","webpack:///./~/zone.js/dist/zone.js"],"names":[],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,qFAAqF,uBAAuB;AAC5G,mEAAmE;AACnE,gEAAgE;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,eAAe;AACf,eAAe;AACf,eAAe;AACf,gBAAgB;AAChB,yB;;;;;;;AC1CA;AACA;AACA,E;;;;;;ACFA;AACA;AACA;AACA,uCAAuC,gC;;;;;;;ACHvC,uBAAuB;AACvB;AACA;AACA,E;;;;;;ACHA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sDAAsD,gBAAgB,EAAE;AACxE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;AClDA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,uB;;;;;;ACVA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,E;;;;;;ACNA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG,UAAU;AACb;AACA;AACA;AACA,E;;;;;;ACfA;AACA;AACA,iCAAiC,QAAQ,gBAAgB,UAAU,GAAG;AACtE,CAAC,E;;;;;;ACHD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,E;;;;;;;;;ACZA;AACA;AACA;AACA,E;;;;;;ACHA,6BAA6B;AAC7B,qCAAqC,gC;;;;;;ACDrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG,UAAU;AACb;AACA,E;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA,CAAC,E;;;;;;;;;AC/BD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAqC,iBAAiB,EAAE;AACxD;AACA;AACA;AACA;AACA;AACA,gEAAgE,gBAAgB;AAChF;AACA;AACA,GAAG,2CAA2C,gCAAgC;AAC9E;AACA;AACA;AACA;AACA;AACA,wB;;;;;;ACxBA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA,E;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAiD;AACjD,CAAC;AACD;AACA,qBAAqB;AACrB;AACA,SAAS;AACT,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACPA;AACA;AACA;AACA;AACA,E;;;;;;;ACJA;;AAEA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;;AAEA;AACA;AACA,4CAA4C;;AAE5C;;;;;;;ACpBA;AACA;AACA;AACA,GAAG;AACH,E;;;;;;ACJA,iBAAiB;;AAEjB;AACA;AACA,E;;;;;;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO,kCAAkC,gCAAgC,aAAa;AACtF,6BAA6B,mCAAmC,aAAa;AAC7E;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,2DAA2D;AAC3D;AACA,gDAAgD,iBAAiB,EAAE;AACnE;AACA,0DAA0D,aAAa,EAAE;AACzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,0B;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA,E;;;;;;ACpFA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA;AACA,a;;;;;;ACHA;AACA;AACA;AACA;AACA,E;;;;;;ACJA,oB;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;;;;;;ACxCA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA;;AAEA;AACA,kEAAkE,+BAA+B;AACjG,E;;;;;;ACNA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA,mDAAmD;AACnD;AACA,uCAAuC;AACvC,E;;;;;;ACLA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACLA;AACA;AACA;AACA;AACA,2DAA2D;AAC3D,E;;;;;;ACLA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;;;;;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe;AACxB;AACA;AACA;AACA,sCAAsC;AACtC;AACA,8BAA8B;AAC9B,6BAA6B;AAC7B,+BAA+B;AAC/B,mCAAmC;AACnC,SAAS,+BAA+B;AACxC;AACA;AACA;AACA;AACA,E;;;;;;;AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,sBAAsB,OAAO;AAC7B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,6BAA6B;AAC7B,0BAA0B;AAC1B,0BAA0B;AAC1B,qBAAqB;AACrB;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,6DAA6D,OAAO;AACpE;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB,qBAAqB;AACrB,0BAA0B;AAC1B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA,E;;;;;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACNA;AACA,qEAAsE,gBAAgB,UAAU,GAAG;AACnG,CAAC,E;;;;;;;ACFD;AACA;AACA;AACA;AACA;;AAEA;AACA,0FAAgF,aAAa,EAAE;;AAE/F;AACA,qDAAqD,0BAA0B;AAC/E;AACA,E;;;;;;ACZA,yC;;;;;;ACAA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;AChBA;AACA;AACA;;AAEA;AACA;AACA,E;;;;;;ACNA,cAAc,sB;;;;;;ACAd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD;AAClD;AACA;AACA;AACA;AACA;AACA,OAAO,UAAU,cAAc;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,GAAG;AACR;AACA,E;;;;;;ACxBA;AACA;AACA;AACA;AACA;AACA,E;;;;;;;;;;;;;;;;;;;;;;;;;;;ACL6B;AACA;AACF;AAI3B;;GAEG;AAEH;;;GAGG;AACH,oDAAoD;;;;;;;;;;;;;;;;;;;;ACdpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iD;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACTA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,WAAW,eAAe;AAC/B;AACA,KAAK;AACL;AACA,E;;;;;;ACpBA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,E;;;;;;ACfA;AACA;;AAEA;AACA;AACA,E;;;;;;;ACLA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,0BAA0B,SAAS;AACnC;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACvBA;AACA;AACA;AACA;AACA,yBAAyB,kBAAkB,EAAE;;AAE7C;AACA;AACA;AACA;AACA,GAAG,UAAU;AACb;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qBAAqB;AACrB,0BAA0B;AAC1B;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA,E;;;;;;AClFA,6E;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,E;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,E;;;;;;ACfA;AACA;AACA;AACA;;AAEA;AACA;AACA,E;;;;;;ACPA;AACA;AACA;AACA;AACA,E;;;;;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,E;;;;;;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,4BAA4B,aAAa;;AAEzC;AACA;AACA;AACA;AACA;AACA,wCAAwC,oCAAoC;AAC5E,4CAA4C,oCAAoC;AAChF,KAAK,2BAA2B,oCAAoC;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAmB;AACnC;AACA;AACA,iCAAiC,2BAA2B;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,E;;;;;;ACrEA;AACA;;AAEA;AACA;AACA,+BAA+B,qBAAqB;AACpD,+BAA+B,SAAS,EAAE;AAC1C,CAAC,UAAU;;AAEX;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,SAAS,mBAAmB;AACvD,+BAA+B,aAAa;AAC5C;AACA,GAAG,UAAU;AACb;AACA,E;;;;;;ACpBA;AACA,UAAU;AACV,E;;;;;;ACFA,uB;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kCAAkC,UAAU,EAAE;AAC9C,mBAAmB,sCAAsC;AACzD,CAAC,oCAAoC;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,CAAC,W;;;;;;AChCD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACZA;AACA;AACA;;AAEA;AACA;AACA,E;;;;;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;;ACTA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,oBAAoB,aAAa;AACjC,GAAG;AACH,E;;;;;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;;;;;;;ACPA;AACA;;AAEA;AACA;AACA,wBAAwB,mEAAmE;AAC3F,CAAC;AACD;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,CAAC,gB;;;;;;AChBD;AACA;AACA;AACA;AACA,qDAAmD;AACnD;AACA;AACA;AACA,qBAAqB;AACrB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACfD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sDAAoD;;AAEpD;AACA;AACA;AACA;AACA,kCAAkC;AAClC,CAAC;AACD;AACA,yBAAyB;AACzB,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;AC9CD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,gCAAgC,MAAM,SAAS,OAAO,SAAS;AAC/D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,CAAC,E;;;;;;ACrBD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;;ACVD;AACA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC,GAAG;AACH,UAAU;AACV,CAAC;;AAED;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACzBD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACTD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACTD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,+BAA+B,SAAS,E;;;;;;ACpBxC;AACA;;AAEA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACPD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,CAAC,E;;;;;;ACVD;AACA;;AAEA,+BAA+B,kCAAgC,E;;;;;;ACH/D;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,CAAC,E;;;;;;ACfD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,CAAC,E;;;;;;ACdD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,+BAA+B,SAAS,E;;;;;;;AC9BxC;AACA;;AAEA;AACA;AACA,wBAAwB,mEAAmE;AAC3F,CAAC;AACD;AACA;AACA;AACA;AACA,CAAC,U;;;;;;;ACXD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL,GAAG;AACH,C;;;;;;ACvDA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA,EAAE,E;;;;;;ACPF;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,E;;;;;;ACdF;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA,EAAE,E;;;;;;AClBF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA,EAAE,E;;;;;;AChBF;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA,EAAE,E;;;;;;ACPF;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA,EAAE,E;;;;;;ACRF;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA,EAAE,E;;;;;;ACfF;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA,EAAE,E;;;;;;ACRF;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,E;;;;;;;;;;;;ACdF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,KAAK;AACL;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,uBAAuB,sBAAsB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,2BAA2B;AAC3B;AACA;AACA;AACA,4BAA4B,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnLtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,qBAAqB;;AAEtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;;AAET;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;;AAET;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;;AAET;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,uBAAuB;AAC9D,uCAAuC,kBAAkB;AACzD,oCAAoC,eAAe;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,kBAAkB;AACzD,uCAAuC,kBAAkB;AACzD,oCAAoC,eAAe;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,0BAA0B;AACrD;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT,kFAAkF,gEAAgE,EAAE;AACpJ;AACA;AACA;AACA;AACA;AACA;AACA,gCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wHAAwH,wBAAwB,oCAAoC;AACpL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C,oDAAoD;AAC9F;AACA;AACA;AACA;AACA;AACA,2BAA2B,mCAAmC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAiD,gBAAgB;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C,sBAAsB;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,+CAA+C,sBAAsB;AACrE;AACA;AACA;AACA;AACA,8CAA8C;AAC9C;AACA;AACA;AACA;AACA;AACA,kBAAkB,EAAE;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,kCAAkC;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2DAA2D,oBAAoB,EAAE;AACjF;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA,iBAAiB;AACjB;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,iCAAiC;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA,8FAA8F,aAAa,EAAE;AAC7G;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA,+BAA+B,8BAA8B;AAC7D;AACA;AACA,iCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,mBAAmB,oBAAoB;AACvC;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,8DAA8D;AAC9D;AACA;AACA,uDAAuD,uDAAuD;AAC9G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,yBAAyB;AAC5C;AACA;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B;AACjE,qCAAqC,yBAAyB;AAC9D,+BAA+B,mBAAmB;AAClD,iCAAiC,0CAA0C;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAyC,wCAAwC;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B;AACjE,iCAAiC,0CAA0C;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA,+BAA+B,gCAAgC;AAC/D,kCAAkC,sCAAsC;AACxE,iCAAiC,0CAA0C;AAC3E;AACA,iDAAiD,2FAA2F,EAAE;AAC9I,oDAAoD,qEAAqE,EAAE;AAC3H;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD,EAAE;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA,iBAAiB;AACjB;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,8DAA8D,0BAA0B;AACxF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,6DAA6D;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sDAAsD,0BAA0B,EAAE;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D,+BAA+B,EAAE;AAC3F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,uFAAuF;AACvF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,mBAAmB,uBAAuB;AAC1C;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,4BAA4B;AAC3C;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uFAAuF;AACvF;AACA;AACA,MAAM,EAAE;AACR,uFAAuF;AACvF;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B;AAC3B;AACA;AACA,MAAM,EAAE;AACR,iGAAiG;AACjG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,EAAE;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8DAA8D,0CAA0C;AACxG;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,CAAC","file":"polyfills.bundle.js","sourcesContent":["var isObject = require('./_is-object');\nmodule.exports = function(it){\n if(!isObject(it))throw TypeError(it + ' is not an object!');\n return it;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_an-object.js\n// module id = 0\n// module chunks = 0","var global = require('./_global')\n , core = require('./_core')\n , hide = require('./_hide')\n , redefine = require('./_redefine')\n , ctx = require('./_ctx')\n , PROTOTYPE = 'prototype';\n\nvar $export = function(type, name, source){\n var IS_FORCED = type & $export.F\n , IS_GLOBAL = type & $export.G\n , IS_STATIC = type & $export.S\n , IS_PROTO = type & $export.P\n , IS_BIND = type & $export.B\n , target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]\n , exports = IS_GLOBAL ? core : core[name] || (core[name] = {})\n , expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {})\n , key, own, out, exp;\n if(IS_GLOBAL)source = name;\n for(key in source){\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if(target)redefine(target, key, out, type & $export.U);\n // export\n if(exports[key] != out)hide(exports, key, exp);\n if(IS_PROTO && expProto[key] != out)expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library` \nmodule.exports = $export;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_export.js\n// module id = 1\n// module chunks = 0","module.exports = function(it){\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_is-object.js\n// module id = 3\n// module chunks = 0","// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();\nif(typeof __g == 'number')__g = global; // eslint-disable-line no-undef\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_global.js\n// module id = 4\n// module chunks = 0","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function(it, key){\n return hasOwnProperty.call(it, key);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_has.js\n// module id = 6\n// module chunks = 0","var Map = require('./es6.map')\n , $export = require('./_export')\n , shared = require('./_shared')('metadata')\n , store = shared.store || (shared.store = new (require('./es6.weak-map')));\n\nvar getOrCreateMetadataMap = function(target, targetKey, create){\n var targetMetadata = store.get(target);\n if(!targetMetadata){\n if(!create)return undefined;\n store.set(target, targetMetadata = new Map);\n }\n var keyMetadata = targetMetadata.get(targetKey);\n if(!keyMetadata){\n if(!create)return undefined;\n targetMetadata.set(targetKey, keyMetadata = new Map);\n } return keyMetadata;\n};\nvar ordinaryHasOwnMetadata = function(MetadataKey, O, P){\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? false : metadataMap.has(MetadataKey);\n};\nvar ordinaryGetOwnMetadata = function(MetadataKey, O, P){\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? undefined : metadataMap.get(MetadataKey);\n};\nvar ordinaryDefineOwnMetadata = function(MetadataKey, MetadataValue, O, P){\n getOrCreateMetadataMap(O, P, true).set(MetadataKey, MetadataValue);\n};\nvar ordinaryOwnMetadataKeys = function(target, targetKey){\n var metadataMap = getOrCreateMetadataMap(target, targetKey, false)\n , keys = [];\n if(metadataMap)metadataMap.forEach(function(_, key){ keys.push(key); });\n return keys;\n};\nvar toMetaKey = function(it){\n return it === undefined || typeof it == 'symbol' ? it : String(it);\n};\nvar exp = function(O){\n $export($export.S, 'Reflect', O);\n};\n\nmodule.exports = {\n store: store,\n map: getOrCreateMetadataMap,\n has: ordinaryHasOwnMetadata,\n get: ordinaryGetOwnMetadata,\n set: ordinaryDefineOwnMetadata,\n keys: ordinaryOwnMetadataKeys,\n key: toMetaKey,\n exp: exp\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_metadata.js\n// module id = 7\n// module chunks = 0","var store = require('./_shared')('wks')\n , uid = require('./_uid')\n , Symbol = require('./_global').Symbol\n , USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function(name){\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_wks.js\n// module id = 8\n// module chunks = 0","module.exports = function(exec){\n try {\n return !!exec();\n } catch(e){\n return true;\n }\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_fails.js\n// module id = 9\n// module chunks = 0","var anObject = require('./_an-object')\n , IE8_DOM_DEFINE = require('./_ie8-dom-define')\n , toPrimitive = require('./_to-primitive')\n , dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if(IE8_DOM_DEFINE)try {\n return dP(O, P, Attributes);\n } catch(e){ /* empty */ }\n if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!');\n if('value' in Attributes)O[P] = Attributes.value;\n return O;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-dp.js\n// module id = 10\n// module chunks = 0","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function(){\n return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_descriptors.js\n// module id = 11\n// module chunks = 0","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has')\n , toObject = require('./_to-object')\n , IE_PROTO = require('./_shared-key')('IE_PROTO')\n , ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function(O){\n O = toObject(O);\n if(has(O, IE_PROTO))return O[IE_PROTO];\n if(typeof O.constructor == 'function' && O instanceof O.constructor){\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-gpo.js\n// module id = 12\n// module chunks = 0","module.exports = function(it){\n if(typeof it != 'function')throw TypeError(it + ' is not a function!');\n return it;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_a-function.js\n// module id = 16\n// module chunks = 0","var core = module.exports = {version: '2.4.0'};\nif(typeof __e == 'number')__e = core; // eslint-disable-line no-undef\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_core.js\n// module id = 17\n// module chunks = 0","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function(fn, that, length){\n aFunction(fn);\n if(that === undefined)return fn;\n switch(length){\n case 1: return function(a){\n return fn.call(that, a);\n };\n case 2: return function(a, b){\n return fn.call(that, a, b);\n };\n case 3: return function(a, b, c){\n return fn.call(that, a, b, c);\n };\n }\n return function(/* ...args */){\n return fn.apply(that, arguments);\n };\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_ctx.js\n// module id = 18\n// module chunks = 0","var pIE = require('./_object-pie')\n , createDesc = require('./_property-desc')\n , toIObject = require('./_to-iobject')\n , toPrimitive = require('./_to-primitive')\n , has = require('./_has')\n , IE8_DOM_DEFINE = require('./_ie8-dom-define')\n , gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P){\n O = toIObject(O);\n P = toPrimitive(P, true);\n if(IE8_DOM_DEFINE)try {\n return gOPD(O, P);\n } catch(e){ /* empty */ }\n if(has(O, P))return createDesc(!pIE.f.call(O, P), O[P]);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-gopd.js\n// module id = 19\n// module chunks = 0","var global = require('./_global')\n , hide = require('./_hide')\n , has = require('./_has')\n , SRC = require('./_uid')('src')\n , TO_STRING = 'toString'\n , $toString = Function[TO_STRING]\n , TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function(it){\n return $toString.call(it);\n};\n\n(module.exports = function(O, key, val, safe){\n var isFunction = typeof val == 'function';\n if(isFunction)has(val, 'name') || hide(val, 'name', key);\n if(O[key] === val)return;\n if(isFunction)has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if(O === global){\n O[key] = val;\n } else {\n if(!safe){\n delete O[key];\n hide(O, key, val);\n } else {\n if(O[key])O[key] = val;\n else hide(O, key, val);\n }\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString(){\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_redefine.js\n// module id = 20\n// module chunks = 0","var ctx = require('./_ctx')\n , call = require('./_iter-call')\n , isArrayIter = require('./_is-array-iter')\n , anObject = require('./_an-object')\n , toLength = require('./_to-length')\n , getIterFn = require('./core.get-iterator-method')\n , BREAK = {}\n , RETURN = {};\nvar exports = module.exports = function(iterable, entries, fn, that, ITERATOR){\n var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable)\n , f = ctx(fn, that, entries ? 2 : 1)\n , index = 0\n , length, step, iterator, result;\n if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if(result === BREAK || result === RETURN)return result;\n } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){\n result = call(iterator, f, step.value, entries);\n if(result === BREAK || result === RETURN)return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_for-of.js\n// module id = 24\n// module chunks = 0","var dP = require('./_object-dp')\n , createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function(object, key, value){\n return dP.f(object, key, createDesc(1, value));\n} : function(object, key, value){\n object[key] = value;\n return object;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_hide.js\n// module id = 25\n// module chunks = 0","var META = require('./_uid')('meta')\n , isObject = require('./_is-object')\n , has = require('./_has')\n , setDesc = require('./_object-dp').f\n , id = 0;\nvar isExtensible = Object.isExtensible || function(){\n return true;\n};\nvar FREEZE = !require('./_fails')(function(){\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function(it){\n setDesc(it, META, {value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n }});\n};\nvar fastKey = function(it, create){\n // return primitive with prefix\n if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if(!has(it, META)){\n // can't set metadata to uncaught frozen object\n if(!isExtensible(it))return 'F';\n // not necessary to add metadata\n if(!create)return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function(it, create){\n if(!has(it, META)){\n // can't set metadata to uncaught frozen object\n if(!isExtensible(it))return true;\n // not necessary to add metadata\n if(!create)return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function(it){\n if(FREEZE && meta.NEED && isExtensible(it) && !has(it, META))setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_meta.js\n// module id = 26\n// module chunks = 0","module.exports = function(bitmap, value){\n return {\n enumerable : !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable : !(bitmap & 4),\n value : value\n };\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_property-desc.js\n// module id = 27\n// module chunks = 0","var id = 0\n , px = Math.random();\nmodule.exports = function(key){\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_uid.js\n// module id = 28\n// module chunks = 0","var g;\r\n\r\n// This works in non-strict mode\r\ng = (function() {\r\n\treturn this;\r\n})();\r\n\r\ntry {\r\n\t// This works if eval is allowed (see CSP)\r\n\tg = g || Function(\"return this\")() || (1,eval)(\"this\");\r\n} catch(e) {\r\n\t// This works if the window reference is available\r\n\tif(typeof window === \"object\")\r\n\t\tg = window;\r\n}\r\n\r\n// g can still be undefined, but nothing to do about it...\r\n// We return undefined, instead of nothing here, so it's\r\n// easier to handle this case. if(!global) { ...}\r\n\r\nmodule.exports = g;\r\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// (webpack)/buildin/global.js\n// module id = 30\n// module chunks = 0 3","module.exports = function(it, Constructor, name, forbiddenField){\n if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_an-instance.js\n// module id = 31\n// module chunks = 0","var toString = {}.toString;\n\nmodule.exports = function(it){\n return toString.call(it).slice(8, -1);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_cof.js\n// module id = 32\n// module chunks = 0","'use strict';\nvar global = require('./_global')\n , $export = require('./_export')\n , redefine = require('./_redefine')\n , redefineAll = require('./_redefine-all')\n , meta = require('./_meta')\n , forOf = require('./_for-of')\n , anInstance = require('./_an-instance')\n , isObject = require('./_is-object')\n , fails = require('./_fails')\n , $iterDetect = require('./_iter-detect')\n , setToStringTag = require('./_set-to-string-tag')\n , inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){\n var Base = global[NAME]\n , C = Base\n , ADDER = IS_MAP ? 'set' : 'add'\n , proto = C && C.prototype\n , O = {};\n var fixMethod = function(KEY){\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function(a){\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a){\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a){\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a){ fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b){ fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if(typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){\n new C().entries().next();\n }))){\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C\n // early implementations not supports chaining\n , HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n , THROWS_ON_PRIMITIVES = fails(function(){ instance.has(1); })\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n , ACCEPT_ITERABLES = $iterDetect(function(iter){ new C(iter); }) // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n , BUGGY_ZERO = !IS_WEAK && fails(function(){\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C()\n , index = 5;\n while(index--)$instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if(!ACCEPT_ITERABLES){ \n C = wrapper(function(target, iterable){\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base, target, C);\n if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if(THROWS_ON_PRIMITIVES || BUGGY_ZERO){\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if(BUGGY_ZERO || HASNT_CHAINING)fixMethod(ADDER);\n // weak collections should not contains .clear method\n if(IS_WEAK && proto.clear)delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_collection.js\n// module id = 33\n// module chunks = 0","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function(it){\n if(it == undefined)throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_defined.js\n// module id = 34\n// module chunks = 0","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_enum-bug-keys.js\n// module id = 35\n// module chunks = 0","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iobject.js\n// module id = 36\n// module chunks = 0","module.exports = {};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iterators.js\n// module id = 37\n// module chunks = 0","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object')\n , dPs = require('./_object-dps')\n , enumBugKeys = require('./_enum-bug-keys')\n , IE_PROTO = require('./_shared-key')('IE_PROTO')\n , Empty = function(){ /* empty */ }\n , PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function(){\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe')\n , i = enumBugKeys.length\n , lt = '<'\n , gt = '>'\n , iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties){\n var result;\n if(O !== null){\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty;\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-create.js\n// module id = 38\n// module chunks = 0","var redefine = require('./_redefine');\nmodule.exports = function(target, src, safe){\n for(var key in src)redefine(target, key, src[key], safe);\n return target;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_redefine-all.js\n// module id = 39\n// module chunks = 0","var def = require('./_object-dp').f\n , has = require('./_has')\n , TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function(it, tag, stat){\n if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag});\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_set-to-string-tag.js\n// module id = 40\n// module chunks = 0","var shared = require('./_shared')('keys')\n , uid = require('./_uid');\nmodule.exports = function(key){\n return shared[key] || (shared[key] = uid(key));\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_shared-key.js\n// module id = 41\n// module chunks = 0","var global = require('./_global')\n , SHARED = '__core-js_shared__'\n , store = global[SHARED] || (global[SHARED] = {});\nmodule.exports = function(key){\n return store[key] || (store[key] = {});\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_shared.js\n// module id = 42\n// module chunks = 0","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject')\n , defined = require('./_defined');\nmodule.exports = function(it){\n return IObject(defined(it));\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-iobject.js\n// module id = 43\n// module chunks = 0","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer')\n , min = Math.min;\nmodule.exports = function(it){\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-length.js\n// module id = 44\n// module chunks = 0","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function(it){\n return Object(defined(it));\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-object.js\n// module id = 45\n// module chunks = 0","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function(it, S){\n if(!isObject(it))return it;\n var fn, val;\n if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;\n if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val;\n if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-primitive.js\n// module id = 46\n// module chunks = 0","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx')\n , IObject = require('./_iobject')\n , toObject = require('./_to-object')\n , toLength = require('./_to-length')\n , asc = require('./_array-species-create');\nmodule.exports = function(TYPE, $create){\n var IS_MAP = TYPE == 1\n , IS_FILTER = TYPE == 2\n , IS_SOME = TYPE == 3\n , IS_EVERY = TYPE == 4\n , IS_FIND_INDEX = TYPE == 6\n , NO_HOLES = TYPE == 5 || IS_FIND_INDEX\n , create = $create || asc;\n return function($this, callbackfn, that){\n var O = toObject($this)\n , self = IObject(O)\n , f = ctx(callbackfn, that, 3)\n , length = toLength(self.length)\n , index = 0\n , result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined\n , val, res;\n for(;length > index; index++)if(NO_HOLES || index in self){\n val = self[index];\n res = f(val, index, O);\n if(TYPE){\n if(IS_MAP)result[index] = res; // map\n else if(res)switch(TYPE){\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if(IS_EVERY)return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_array-methods.js\n// module id = 52\n// module chunks = 0","'use strict';\nvar dP = require('./_object-dp').f\n , create = require('./_object-create')\n , redefineAll = require('./_redefine-all')\n , ctx = require('./_ctx')\n , anInstance = require('./_an-instance')\n , defined = require('./_defined')\n , forOf = require('./_for-of')\n , $iterDefine = require('./_iter-define')\n , step = require('./_iter-step')\n , setSpecies = require('./_set-species')\n , DESCRIPTORS = require('./_descriptors')\n , fastKey = require('./_meta').fastKey\n , SIZE = DESCRIPTORS ? '_s' : 'size';\n\nvar getEntry = function(that, key){\n // fast case\n var index = fastKey(key), entry;\n if(index !== 'F')return that._i[index];\n // frozen object case\n for(entry = that._f; entry; entry = entry.n){\n if(entry.k == key)return entry;\n }\n};\n\nmodule.exports = {\n getConstructor: function(wrapper, NAME, IS_MAP, ADDER){\n var C = wrapper(function(that, iterable){\n anInstance(that, C, NAME, '_i');\n that._i = create(null); // index\n that._f = undefined; // first entry\n that._l = undefined; // last entry\n that[SIZE] = 0; // size\n if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.1.3.1 Map.prototype.clear()\n // 23.2.3.2 Set.prototype.clear()\n clear: function clear(){\n for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){\n entry.r = true;\n if(entry.p)entry.p = entry.p.n = undefined;\n delete data[entry.i];\n }\n that._f = that._l = undefined;\n that[SIZE] = 0;\n },\n // 23.1.3.3 Map.prototype.delete(key)\n // 23.2.3.4 Set.prototype.delete(value)\n 'delete': function(key){\n var that = this\n , entry = getEntry(that, key);\n if(entry){\n var next = entry.n\n , prev = entry.p;\n delete that._i[entry.i];\n entry.r = true;\n if(prev)prev.n = next;\n if(next)next.p = prev;\n if(that._f == entry)that._f = next;\n if(that._l == entry)that._l = prev;\n that[SIZE]--;\n } return !!entry;\n },\n // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)\n // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)\n forEach: function forEach(callbackfn /*, that = undefined */){\n anInstance(this, C, 'forEach');\n var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3)\n , entry;\n while(entry = entry ? entry.n : this._f){\n f(entry.v, entry.k, this);\n // revert to the last existing entry\n while(entry && entry.r)entry = entry.p;\n }\n },\n // 23.1.3.7 Map.prototype.has(key)\n // 23.2.3.7 Set.prototype.has(value)\n has: function has(key){\n return !!getEntry(this, key);\n }\n });\n if(DESCRIPTORS)dP(C.prototype, 'size', {\n get: function(){\n return defined(this[SIZE]);\n }\n });\n return C;\n },\n def: function(that, key, value){\n var entry = getEntry(that, key)\n , prev, index;\n // change existing entry\n if(entry){\n entry.v = value;\n // create new entry\n } else {\n that._l = entry = {\n i: index = fastKey(key, true), // <- index\n k: key, // <- key\n v: value, // <- value\n p: prev = that._l, // <- previous entry\n n: undefined, // <- next entry\n r: false // <- removed\n };\n if(!that._f)that._f = entry;\n if(prev)prev.n = entry;\n that[SIZE]++;\n // add to index\n if(index !== 'F')that._i[index] = entry;\n } return that;\n },\n getEntry: getEntry,\n setStrong: function(C, NAME, IS_MAP){\n // add .keys, .values, .entries, [@@iterator]\n // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11\n $iterDefine(C, NAME, function(iterated, kind){\n this._t = iterated; // target\n this._k = kind; // kind\n this._l = undefined; // previous\n }, function(){\n var that = this\n , kind = that._k\n , entry = that._l;\n // revert to the last existing entry\n while(entry && entry.r)entry = entry.p;\n // get next entry\n if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){\n // or finish the iteration\n that._t = undefined;\n return step(1);\n }\n // return step by kind\n if(kind == 'keys' )return step(0, entry.k);\n if(kind == 'values')return step(0, entry.v);\n return step(0, [entry.k, entry.v]);\n }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true);\n\n // add [@@species], 23.1.2.2, 23.2.2.2\n setSpecies(NAME);\n }\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_collection-strong.js\n// module id = 53\n// module chunks = 0","var isObject = require('./_is-object')\n , document = require('./_global').document\n // in old IE typeof document.createElement is 'object'\n , is = isObject(document) && isObject(document.createElement);\nmodule.exports = function(it){\n return is ? document.createElement(it) : {};\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_dom-create.js\n// module id = 54\n// module chunks = 0","module.exports = !require('./_descriptors') && !require('./_fails')(function(){\n return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7;\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_ie8-dom-define.js\n// module id = 55\n// module chunks = 0","'use strict';\nvar create = require('./_object-create')\n , descriptor = require('./_property-desc')\n , setToStringTag = require('./_set-to-string-tag')\n , IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function(){ return this; });\n\nmodule.exports = function(Constructor, NAME, next){\n Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)});\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iter-create.js\n// module id = 56\n// module chunks = 0","exports.f = Object.getOwnPropertySymbols;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-gops.js\n// module id = 57\n// module chunks = 0","var has = require('./_has')\n , toIObject = require('./_to-iobject')\n , arrayIndexOf = require('./_array-includes')(false)\n , IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function(object, names){\n var O = toIObject(object)\n , i = 0\n , result = []\n , key;\n for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while(names.length > i)if(has(O, key = names[i++])){\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-keys-internal.js\n// module id = 58\n// module chunks = 0","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal')\n , enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O){\n return $keys(O, enumBugKeys);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-keys.js\n// module id = 59\n// module chunks = 0","exports.f = {}.propertyIsEnumerable;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-pie.js\n// module id = 60\n// module chunks = 0","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object')\n , anObject = require('./_an-object');\nvar check = function(O, proto){\n anObject(O);\n if(!isObject(proto) && proto !== null)throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function(test, buggy, set){\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch(e){ buggy = true; }\n return function setPrototypeOf(O, proto){\n check(O, proto);\n if(buggy)O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_set-proto.js\n// module id = 61\n// module chunks = 0","// 7.1.4 ToInteger\nvar ceil = Math.ceil\n , floor = Math.floor;\nmodule.exports = function(it){\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-integer.js\n// module id = 62\n// module chunks = 0","import \"core-js/es6/reflect\";\r\nimport \"core-js/es7/reflect\";\r\nimport \"zone.js/dist/zone\";\r\n\r\n\r\n\r\n/***************************************************************************************************\r\n * APPLICATION IMPORTS\r\n */\r\n\r\n/**\r\n * Date, currency, decimal and percent pipes.\r\n * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10\r\n */\r\n// import 'intl'; // Run `npm install --save intl`.\r\n\n\n\n// WEBPACK FOOTER //\n// ./src/polyfills.ts","require('../modules/es6.reflect.apply');\nrequire('../modules/es6.reflect.construct');\nrequire('../modules/es6.reflect.define-property');\nrequire('../modules/es6.reflect.delete-property');\nrequire('../modules/es6.reflect.enumerate');\nrequire('../modules/es6.reflect.get');\nrequire('../modules/es6.reflect.get-own-property-descriptor');\nrequire('../modules/es6.reflect.get-prototype-of');\nrequire('../modules/es6.reflect.has');\nrequire('../modules/es6.reflect.is-extensible');\nrequire('../modules/es6.reflect.own-keys');\nrequire('../modules/es6.reflect.prevent-extensions');\nrequire('../modules/es6.reflect.set');\nrequire('../modules/es6.reflect.set-prototype-of');\nmodule.exports = require('../modules/_core').Reflect;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/es6/reflect.js\n// module id = 90\n// module chunks = 0","require('../modules/es7.reflect.define-metadata');\nrequire('../modules/es7.reflect.delete-metadata');\nrequire('../modules/es7.reflect.get-metadata');\nrequire('../modules/es7.reflect.get-metadata-keys');\nrequire('../modules/es7.reflect.get-own-metadata');\nrequire('../modules/es7.reflect.get-own-metadata-keys');\nrequire('../modules/es7.reflect.has-metadata');\nrequire('../modules/es7.reflect.has-own-metadata');\nrequire('../modules/es7.reflect.metadata');\nmodule.exports = require('../modules/_core').Reflect;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/es7/reflect.js\n// module id = 91\n// module chunks = 0","var forOf = require('./_for-of');\n\nmodule.exports = function(iter, ITERATOR){\n var result = [];\n forOf(iter, false, result.push, result, ITERATOR);\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_array-from-iterable.js\n// module id = 92\n// module chunks = 0","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject')\n , toLength = require('./_to-length')\n , toIndex = require('./_to-index');\nmodule.exports = function(IS_INCLUDES){\n return function($this, el, fromIndex){\n var O = toIObject($this)\n , length = toLength(O.length)\n , index = toIndex(fromIndex, length)\n , value;\n // Array#includes uses SameValueZero equality algorithm\n if(IS_INCLUDES && el != el)while(length > index){\n value = O[index++];\n if(value != value)return true;\n // Array#toIndex ignores holes, Array#includes - not\n } else for(;length > index; index++)if(IS_INCLUDES || index in O){\n if(O[index] === el)return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_array-includes.js\n// module id = 93\n// module chunks = 0","var isObject = require('./_is-object')\n , isArray = require('./_is-array')\n , SPECIES = require('./_wks')('species');\n\nmodule.exports = function(original){\n var C;\n if(isArray(original)){\n C = original.constructor;\n // cross-realm fallback\n if(typeof C == 'function' && (C === Array || isArray(C.prototype)))C = undefined;\n if(isObject(C)){\n C = C[SPECIES];\n if(C === null)C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_array-species-constructor.js\n// module id = 94\n// module chunks = 0","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function(original, length){\n return new (speciesConstructor(original))(length);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_array-species-create.js\n// module id = 95\n// module chunks = 0","'use strict';\nvar aFunction = require('./_a-function')\n , isObject = require('./_is-object')\n , invoke = require('./_invoke')\n , arraySlice = [].slice\n , factories = {};\n\nvar construct = function(F, len, args){\n if(!(len in factories)){\n for(var n = [], i = 0; i < len; i++)n[i] = 'a[' + i + ']';\n factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')');\n } return factories[len](F, args);\n};\n\nmodule.exports = Function.bind || function bind(that /*, args... */){\n var fn = aFunction(this)\n , partArgs = arraySlice.call(arguments, 1);\n var bound = function(/* args... */){\n var args = partArgs.concat(arraySlice.call(arguments));\n return this instanceof bound ? construct(fn, args.length, args) : invoke(fn, args, that);\n };\n if(isObject(fn.prototype))bound.prototype = fn.prototype;\n return bound;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_bind.js\n// module id = 96\n// module chunks = 0","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof')\n , TAG = require('./_wks')('toStringTag')\n // ES3 wrong here\n , ARG = cof(function(){ return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function(it, key){\n try {\n return it[key];\n } catch(e){ /* empty */ }\n};\n\nmodule.exports = function(it){\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_classof.js\n// module id = 97\n// module chunks = 0","'use strict';\nvar redefineAll = require('./_redefine-all')\n , getWeak = require('./_meta').getWeak\n , anObject = require('./_an-object')\n , isObject = require('./_is-object')\n , anInstance = require('./_an-instance')\n , forOf = require('./_for-of')\n , createArrayMethod = require('./_array-methods')\n , $has = require('./_has')\n , arrayFind = createArrayMethod(5)\n , arrayFindIndex = createArrayMethod(6)\n , id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function(that){\n return that._l || (that._l = new UncaughtFrozenStore);\n};\nvar UncaughtFrozenStore = function(){\n this.a = [];\n};\nvar findUncaughtFrozen = function(store, key){\n return arrayFind(store.a, function(it){\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function(key){\n var entry = findUncaughtFrozen(this, key);\n if(entry)return entry[1];\n },\n has: function(key){\n return !!findUncaughtFrozen(this, key);\n },\n set: function(key, value){\n var entry = findUncaughtFrozen(this, key);\n if(entry)entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function(key){\n var index = arrayFindIndex(this.a, function(it){\n return it[0] === key;\n });\n if(~index)this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function(wrapper, NAME, IS_MAP, ADDER){\n var C = wrapper(function(that, iterable){\n anInstance(that, C, NAME, '_i');\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function(key){\n if(!isObject(key))return false;\n var data = getWeak(key);\n if(data === true)return uncaughtFrozenStore(this)['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key){\n if(!isObject(key))return false;\n var data = getWeak(key);\n if(data === true)return uncaughtFrozenStore(this).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function(that, key, value){\n var data = getWeak(anObject(key), true);\n if(data === true)uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_collection-weak.js\n// module id = 98\n// module chunks = 0","module.exports = require('./_global').document && document.documentElement;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_html.js\n// module id = 99\n// module chunks = 0","var isObject = require('./_is-object')\n , setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function(that, target, C){\n var P, S = target.constructor;\n if(S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf){\n setPrototypeOf(that, P);\n } return that;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_inherit-if-required.js\n// module id = 100\n// module chunks = 0","// fast apply, http://jsperf.lnkit.com/fast-apply/5\nmodule.exports = function(fn, args, that){\n var un = that === undefined;\n switch(args.length){\n case 0: return un ? fn()\n : fn.call(that);\n case 1: return un ? fn(args[0])\n : fn.call(that, args[0]);\n case 2: return un ? fn(args[0], args[1])\n : fn.call(that, args[0], args[1]);\n case 3: return un ? fn(args[0], args[1], args[2])\n : fn.call(that, args[0], args[1], args[2]);\n case 4: return un ? fn(args[0], args[1], args[2], args[3])\n : fn.call(that, args[0], args[1], args[2], args[3]);\n } return fn.apply(that, args);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_invoke.js\n// module id = 101\n// module chunks = 0","// check on default Array iterator\nvar Iterators = require('./_iterators')\n , ITERATOR = require('./_wks')('iterator')\n , ArrayProto = Array.prototype;\n\nmodule.exports = function(it){\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_is-array-iter.js\n// module id = 102\n// module chunks = 0","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg){\n return cof(arg) == 'Array';\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_is-array.js\n// module id = 103\n// module chunks = 0","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function(iterator, fn, value, entries){\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch(e){\n var ret = iterator['return'];\n if(ret !== undefined)anObject(ret.call(iterator));\n throw e;\n }\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iter-call.js\n// module id = 104\n// module chunks = 0","'use strict';\nvar LIBRARY = require('./_library')\n , $export = require('./_export')\n , redefine = require('./_redefine')\n , hide = require('./_hide')\n , has = require('./_has')\n , Iterators = require('./_iterators')\n , $iterCreate = require('./_iter-create')\n , setToStringTag = require('./_set-to-string-tag')\n , getPrototypeOf = require('./_object-gpo')\n , ITERATOR = require('./_wks')('iterator')\n , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next`\n , FF_ITERATOR = '@@iterator'\n , KEYS = 'keys'\n , VALUES = 'values';\n\nvar returnThis = function(){ return this; };\n\nmodule.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){\n $iterCreate(Constructor, NAME, next);\n var getMethod = function(kind){\n if(!BUGGY && kind in proto)return proto[kind];\n switch(kind){\n case KEYS: return function keys(){ return new Constructor(this, kind); };\n case VALUES: return function values(){ return new Constructor(this, kind); };\n } return function entries(){ return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator'\n , DEF_VALUES = DEFAULT == VALUES\n , VALUES_BUG = false\n , proto = Base.prototype\n , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]\n , $default = $native || getMethod(DEFAULT)\n , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined\n , $anyNative = NAME == 'Array' ? proto.entries || $native : $native\n , methods, key, IteratorPrototype;\n // Fix native\n if($anyNative){\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base));\n if(IteratorPrototype !== Object.prototype){\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if(DEF_VALUES && $native && $native.name !== VALUES){\n VALUES_BUG = true;\n $default = function values(){ return $native.call(this); };\n }\n // Define iterator\n if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if(DEFAULT){\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if(FORCED)for(key in methods){\n if(!(key in proto))redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iter-define.js\n// module id = 105\n// module chunks = 0","var ITERATOR = require('./_wks')('iterator')\n , SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function(){ SAFE_CLOSING = true; };\n Array.from(riter, function(){ throw 2; });\n} catch(e){ /* empty */ }\n\nmodule.exports = function(exec, skipClosing){\n if(!skipClosing && !SAFE_CLOSING)return false;\n var safe = false;\n try {\n var arr = [7]\n , iter = arr[ITERATOR]();\n iter.next = function(){ return {done: safe = true}; };\n arr[ITERATOR] = function(){ return iter; };\n exec(arr);\n } catch(e){ /* empty */ }\n return safe;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iter-detect.js\n// module id = 106\n// module chunks = 0","module.exports = function(done, value){\n return {value: value, done: !!done};\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_iter-step.js\n// module id = 107\n// module chunks = 0","module.exports = false;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_library.js\n// module id = 108\n// module chunks = 0","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar getKeys = require('./_object-keys')\n , gOPS = require('./_object-gops')\n , pIE = require('./_object-pie')\n , toObject = require('./_to-object')\n , IObject = require('./_iobject')\n , $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function(){\n var A = {}\n , B = {}\n , S = Symbol()\n , K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function(k){ B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source){ // eslint-disable-line no-unused-vars\n var T = toObject(target)\n , aLen = arguments.length\n , index = 1\n , getSymbols = gOPS.f\n , isEnum = pIE.f;\n while(aLen > index){\n var S = IObject(arguments[index++])\n , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S)\n , length = keys.length\n , j = 0\n , key;\n while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key];\n } return T;\n} : $assign;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-assign.js\n// module id = 109\n// module chunks = 0","var dP = require('./_object-dp')\n , anObject = require('./_an-object')\n , getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties){\n anObject(O);\n var keys = getKeys(Properties)\n , length = keys.length\n , i = 0\n , P;\n while(length > i)dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-dps.js\n// module id = 110\n// module chunks = 0","// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)\nvar $keys = require('./_object-keys-internal')\n , hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype');\n\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O){\n return $keys(O, hiddenKeys);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_object-gopn.js\n// module id = 111\n// module chunks = 0","// all object keys, includes non-enumerable and symbols\nvar gOPN = require('./_object-gopn')\n , gOPS = require('./_object-gops')\n , anObject = require('./_an-object')\n , Reflect = require('./_global').Reflect;\nmodule.exports = Reflect && Reflect.ownKeys || function ownKeys(it){\n var keys = gOPN.f(anObject(it))\n , getSymbols = gOPS.f;\n return getSymbols ? keys.concat(getSymbols(it)) : keys;\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_own-keys.js\n// module id = 112\n// module chunks = 0","'use strict';\nvar global = require('./_global')\n , dP = require('./_object-dp')\n , DESCRIPTORS = require('./_descriptors')\n , SPECIES = require('./_wks')('species');\n\nmodule.exports = function(KEY){\n var C = global[KEY];\n if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, {\n configurable: true,\n get: function(){ return this; }\n });\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_set-species.js\n// module id = 113\n// module chunks = 0","var toInteger = require('./_to-integer')\n , max = Math.max\n , min = Math.min;\nmodule.exports = function(index, length){\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/_to-index.js\n// module id = 114\n// module chunks = 0","var classof = require('./_classof')\n , ITERATOR = require('./_wks')('iterator')\n , Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function(it){\n if(it != undefined)return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/core.get-iterator-method.js\n// module id = 115\n// module chunks = 0","'use strict';\nvar strong = require('./_collection-strong');\n\n// 23.1 Map Objects\nmodule.exports = require('./_collection')('Map', function(get){\n return function Map(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.1.3.6 Map.prototype.get(key)\n get: function get(key){\n var entry = strong.getEntry(this, key);\n return entry && entry.v;\n },\n // 23.1.3.9 Map.prototype.set(key, value)\n set: function set(key, value){\n return strong.def(this, key === 0 ? 0 : key, value);\n }\n}, strong, true);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.map.js\n// module id = 116\n// module chunks = 0","// 26.1.1 Reflect.apply(target, thisArgument, argumentsList)\nvar $export = require('./_export')\n , aFunction = require('./_a-function')\n , anObject = require('./_an-object')\n , rApply = (require('./_global').Reflect || {}).apply\n , fApply = Function.apply;\n// MS Edge argumentsList argument is optional\n$export($export.S + $export.F * !require('./_fails')(function(){\n rApply(function(){});\n}), 'Reflect', {\n apply: function apply(target, thisArgument, argumentsList){\n var T = aFunction(target)\n , L = anObject(argumentsList);\n return rApply ? rApply(T, thisArgument, L) : fApply.call(T, thisArgument, L);\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.apply.js\n// module id = 117\n// module chunks = 0","// 26.1.2 Reflect.construct(target, argumentsList [, newTarget])\nvar $export = require('./_export')\n , create = require('./_object-create')\n , aFunction = require('./_a-function')\n , anObject = require('./_an-object')\n , isObject = require('./_is-object')\n , fails = require('./_fails')\n , bind = require('./_bind')\n , rConstruct = (require('./_global').Reflect || {}).construct;\n\n// MS Edge supports only 2 arguments and argumentsList argument is optional\n// FF Nightly sets third argument as `new.target`, but does not create `this` from it\nvar NEW_TARGET_BUG = fails(function(){\n function F(){}\n return !(rConstruct(function(){}, [], F) instanceof F);\n});\nvar ARGS_BUG = !fails(function(){\n rConstruct(function(){});\n});\n\n$export($export.S + $export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', {\n construct: function construct(Target, args /*, newTarget*/){\n aFunction(Target);\n anObject(args);\n var newTarget = arguments.length < 3 ? Target : aFunction(arguments[2]);\n if(ARGS_BUG && !NEW_TARGET_BUG)return rConstruct(Target, args, newTarget);\n if(Target == newTarget){\n // w/o altered newTarget, optimization for 0-4 arguments\n switch(args.length){\n case 0: return new Target;\n case 1: return new Target(args[0]);\n case 2: return new Target(args[0], args[1]);\n case 3: return new Target(args[0], args[1], args[2]);\n case 4: return new Target(args[0], args[1], args[2], args[3]);\n }\n // w/o altered newTarget, lot of arguments case\n var $args = [null];\n $args.push.apply($args, args);\n return new (bind.apply(Target, $args));\n }\n // with altered newTarget, not support built-in constructors\n var proto = newTarget.prototype\n , instance = create(isObject(proto) ? proto : Object.prototype)\n , result = Function.apply.call(Target, instance, args);\n return isObject(result) ? result : instance;\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.construct.js\n// module id = 118\n// module chunks = 0","// 26.1.3 Reflect.defineProperty(target, propertyKey, attributes)\nvar dP = require('./_object-dp')\n , $export = require('./_export')\n , anObject = require('./_an-object')\n , toPrimitive = require('./_to-primitive');\n\n// MS Edge has broken Reflect.defineProperty - throwing instead of returning false\n$export($export.S + $export.F * require('./_fails')(function(){\n Reflect.defineProperty(dP.f({}, 1, {value: 1}), 1, {value: 2});\n}), 'Reflect', {\n defineProperty: function defineProperty(target, propertyKey, attributes){\n anObject(target);\n propertyKey = toPrimitive(propertyKey, true);\n anObject(attributes);\n try {\n dP.f(target, propertyKey, attributes);\n return true;\n } catch(e){\n return false;\n }\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.define-property.js\n// module id = 119\n// module chunks = 0","// 26.1.4 Reflect.deleteProperty(target, propertyKey)\nvar $export = require('./_export')\n , gOPD = require('./_object-gopd').f\n , anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n deleteProperty: function deleteProperty(target, propertyKey){\n var desc = gOPD(anObject(target), propertyKey);\n return desc && !desc.configurable ? false : delete target[propertyKey];\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.delete-property.js\n// module id = 120\n// module chunks = 0","'use strict';\n// 26.1.5 Reflect.enumerate(target)\nvar $export = require('./_export')\n , anObject = require('./_an-object');\nvar Enumerate = function(iterated){\n this._t = anObject(iterated); // target\n this._i = 0; // next index\n var keys = this._k = [] // keys\n , key;\n for(key in iterated)keys.push(key);\n};\nrequire('./_iter-create')(Enumerate, 'Object', function(){\n var that = this\n , keys = that._k\n , key;\n do {\n if(that._i >= keys.length)return {value: undefined, done: true};\n } while(!((key = keys[that._i++]) in that._t));\n return {value: key, done: false};\n});\n\n$export($export.S, 'Reflect', {\n enumerate: function enumerate(target){\n return new Enumerate(target);\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.enumerate.js\n// module id = 121\n// module chunks = 0","// 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey)\nvar gOPD = require('./_object-gopd')\n , $export = require('./_export')\n , anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey){\n return gOPD.f(anObject(target), propertyKey);\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.get-own-property-descriptor.js\n// module id = 122\n// module chunks = 0","// 26.1.8 Reflect.getPrototypeOf(target)\nvar $export = require('./_export')\n , getProto = require('./_object-gpo')\n , anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getPrototypeOf: function getPrototypeOf(target){\n return getProto(anObject(target));\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.get-prototype-of.js\n// module id = 123\n// module chunks = 0","// 26.1.6 Reflect.get(target, propertyKey [, receiver])\nvar gOPD = require('./_object-gopd')\n , getPrototypeOf = require('./_object-gpo')\n , has = require('./_has')\n , $export = require('./_export')\n , isObject = require('./_is-object')\n , anObject = require('./_an-object');\n\nfunction get(target, propertyKey/*, receiver*/){\n var receiver = arguments.length < 3 ? target : arguments[2]\n , desc, proto;\n if(anObject(target) === receiver)return target[propertyKey];\n if(desc = gOPD.f(target, propertyKey))return has(desc, 'value')\n ? desc.value\n : desc.get !== undefined\n ? desc.get.call(receiver)\n : undefined;\n if(isObject(proto = getPrototypeOf(target)))return get(proto, propertyKey, receiver);\n}\n\n$export($export.S, 'Reflect', {get: get});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.get.js\n// module id = 124\n// module chunks = 0","// 26.1.9 Reflect.has(target, propertyKey)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', {\n has: function has(target, propertyKey){\n return propertyKey in target;\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.has.js\n// module id = 125\n// module chunks = 0","// 26.1.10 Reflect.isExtensible(target)\nvar $export = require('./_export')\n , anObject = require('./_an-object')\n , $isExtensible = Object.isExtensible;\n\n$export($export.S, 'Reflect', {\n isExtensible: function isExtensible(target){\n anObject(target);\n return $isExtensible ? $isExtensible(target) : true;\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.is-extensible.js\n// module id = 126\n// module chunks = 0","// 26.1.11 Reflect.ownKeys(target)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', {ownKeys: require('./_own-keys')});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.own-keys.js\n// module id = 127\n// module chunks = 0","// 26.1.12 Reflect.preventExtensions(target)\nvar $export = require('./_export')\n , anObject = require('./_an-object')\n , $preventExtensions = Object.preventExtensions;\n\n$export($export.S, 'Reflect', {\n preventExtensions: function preventExtensions(target){\n anObject(target);\n try {\n if($preventExtensions)$preventExtensions(target);\n return true;\n } catch(e){\n return false;\n }\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.prevent-extensions.js\n// module id = 128\n// module chunks = 0","// 26.1.14 Reflect.setPrototypeOf(target, proto)\nvar $export = require('./_export')\n , setProto = require('./_set-proto');\n\nif(setProto)$export($export.S, 'Reflect', {\n setPrototypeOf: function setPrototypeOf(target, proto){\n setProto.check(target, proto);\n try {\n setProto.set(target, proto);\n return true;\n } catch(e){\n return false;\n }\n }\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.set-prototype-of.js\n// module id = 129\n// module chunks = 0","// 26.1.13 Reflect.set(target, propertyKey, V [, receiver])\nvar dP = require('./_object-dp')\n , gOPD = require('./_object-gopd')\n , getPrototypeOf = require('./_object-gpo')\n , has = require('./_has')\n , $export = require('./_export')\n , createDesc = require('./_property-desc')\n , anObject = require('./_an-object')\n , isObject = require('./_is-object');\n\nfunction set(target, propertyKey, V/*, receiver*/){\n var receiver = arguments.length < 4 ? target : arguments[3]\n , ownDesc = gOPD.f(anObject(target), propertyKey)\n , existingDescriptor, proto;\n if(!ownDesc){\n if(isObject(proto = getPrototypeOf(target))){\n return set(proto, propertyKey, V, receiver);\n }\n ownDesc = createDesc(0);\n }\n if(has(ownDesc, 'value')){\n if(ownDesc.writable === false || !isObject(receiver))return false;\n existingDescriptor = gOPD.f(receiver, propertyKey) || createDesc(0);\n existingDescriptor.value = V;\n dP.f(receiver, propertyKey, existingDescriptor);\n return true;\n }\n return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true);\n}\n\n$export($export.S, 'Reflect', {set: set});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.reflect.set.js\n// module id = 130\n// module chunks = 0","'use strict';\nvar strong = require('./_collection-strong');\n\n// 23.2 Set Objects\nmodule.exports = require('./_collection')('Set', function(get){\n return function Set(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.2.3.1 Set.prototype.add(value)\n add: function add(value){\n return strong.def(this, value = value === 0 ? 0 : value, value);\n }\n}, strong);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.set.js\n// module id = 131\n// module chunks = 0","'use strict';\nvar each = require('./_array-methods')(0)\n , redefine = require('./_redefine')\n , meta = require('./_meta')\n , assign = require('./_object-assign')\n , weak = require('./_collection-weak')\n , isObject = require('./_is-object')\n , getWeak = meta.getWeak\n , isExtensible = Object.isExtensible\n , uncaughtFrozenStore = weak.ufstore\n , tmp = {}\n , InternalMap;\n\nvar wrapper = function(get){\n return function WeakMap(){\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key){\n if(isObject(key)){\n var data = getWeak(key);\n if(data === true)return uncaughtFrozenStore(this).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value){\n return weak.def(this, key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')('WeakMap', wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif(new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7){\n InternalMap = weak.getConstructor(wrapper);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function(key){\n var proto = $WeakMap.prototype\n , method = proto[key];\n redefine(proto, key, function(a, b){\n // store frozen objects on internal weakmap shim\n if(isObject(a) && !isExtensible(a)){\n if(!this._f)this._f = new InternalMap;\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es6.weak-map.js\n// module id = 132\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , toMetaKey = metadata.key\n , ordinaryDefineOwnMetadata = metadata.set;\n\nmetadata.exp({defineMetadata: function defineMetadata(metadataKey, metadataValue, target, targetKey){\n ordinaryDefineOwnMetadata(metadataKey, metadataValue, anObject(target), toMetaKey(targetKey));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.define-metadata.js\n// module id = 133\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , toMetaKey = metadata.key\n , getOrCreateMetadataMap = metadata.map\n , store = metadata.store;\n\nmetadata.exp({deleteMetadata: function deleteMetadata(metadataKey, target /*, targetKey */){\n var targetKey = arguments.length < 3 ? undefined : toMetaKey(arguments[2])\n , metadataMap = getOrCreateMetadataMap(anObject(target), targetKey, false);\n if(metadataMap === undefined || !metadataMap['delete'](metadataKey))return false;\n if(metadataMap.size)return true;\n var targetMetadata = store.get(target);\n targetMetadata['delete'](targetKey);\n return !!targetMetadata.size || store['delete'](target);\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.delete-metadata.js\n// module id = 134\n// module chunks = 0","var Set = require('./es6.set')\n , from = require('./_array-from-iterable')\n , metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , getPrototypeOf = require('./_object-gpo')\n , ordinaryOwnMetadataKeys = metadata.keys\n , toMetaKey = metadata.key;\n\nvar ordinaryMetadataKeys = function(O, P){\n var oKeys = ordinaryOwnMetadataKeys(O, P)\n , parent = getPrototypeOf(O);\n if(parent === null)return oKeys;\n var pKeys = ordinaryMetadataKeys(parent, P);\n return pKeys.length ? oKeys.length ? from(new Set(oKeys.concat(pKeys))) : pKeys : oKeys;\n};\n\nmetadata.exp({getMetadataKeys: function getMetadataKeys(target /*, targetKey */){\n return ordinaryMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.get-metadata-keys.js\n// module id = 135\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , getPrototypeOf = require('./_object-gpo')\n , ordinaryHasOwnMetadata = metadata.has\n , ordinaryGetOwnMetadata = metadata.get\n , toMetaKey = metadata.key;\n\nvar ordinaryGetMetadata = function(MetadataKey, O, P){\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if(hasOwn)return ordinaryGetOwnMetadata(MetadataKey, O, P);\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryGetMetadata(MetadataKey, parent, P) : undefined;\n};\n\nmetadata.exp({getMetadata: function getMetadata(metadataKey, target /*, targetKey */){\n return ordinaryGetMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.get-metadata.js\n// module id = 136\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , ordinaryOwnMetadataKeys = metadata.keys\n , toMetaKey = metadata.key;\n\nmetadata.exp({getOwnMetadataKeys: function getOwnMetadataKeys(target /*, targetKey */){\n return ordinaryOwnMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.get-own-metadata-keys.js\n// module id = 137\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , ordinaryGetOwnMetadata = metadata.get\n , toMetaKey = metadata.key;\n\nmetadata.exp({getOwnMetadata: function getOwnMetadata(metadataKey, target /*, targetKey */){\n return ordinaryGetOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.get-own-metadata.js\n// module id = 138\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , getPrototypeOf = require('./_object-gpo')\n , ordinaryHasOwnMetadata = metadata.has\n , toMetaKey = metadata.key;\n\nvar ordinaryHasMetadata = function(MetadataKey, O, P){\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if(hasOwn)return true;\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryHasMetadata(MetadataKey, parent, P) : false;\n};\n\nmetadata.exp({hasMetadata: function hasMetadata(metadataKey, target /*, targetKey */){\n return ordinaryHasMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.has-metadata.js\n// module id = 139\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , ordinaryHasOwnMetadata = metadata.has\n , toMetaKey = metadata.key;\n\nmetadata.exp({hasOwnMetadata: function hasOwnMetadata(metadataKey, target /*, targetKey */){\n return ordinaryHasOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.has-own-metadata.js\n// module id = 140\n// module chunks = 0","var metadata = require('./_metadata')\n , anObject = require('./_an-object')\n , aFunction = require('./_a-function')\n , toMetaKey = metadata.key\n , ordinaryDefineOwnMetadata = metadata.set;\n\nmetadata.exp({metadata: function metadata(metadataKey, metadataValue){\n return function decorator(target, targetKey){\n ordinaryDefineOwnMetadata(\n metadataKey, metadataValue,\n (targetKey !== undefined ? anObject : aFunction)(target),\n toMetaKey(targetKey)\n );\n };\n}});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es7.reflect.metadata.js\n// module id = 141\n// module chunks = 0","// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/process/browser.js\n// module id = 148\n// module chunks = 0","/**\n* @license\n* Copyright Google Inc. All Rights Reserved.\n*\n* Use of this source code is governed by an MIT-style license that can be\n* found in the LICENSE file at https://angular.io/license\n*/\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(factory());\n}(this, (function () { 'use strict';\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar Zone$1 = (function (global) {\n if (global['Zone']) {\n throw new Error('Zone already loaded.');\n }\n var NO_ZONE = { name: 'NO ZONE' };\n var notScheduled = 'notScheduled', scheduling = 'scheduling', scheduled = 'scheduled', running = 'running', canceling = 'canceling', unknown = 'unknown';\n var microTask = 'microTask', macroTask = 'macroTask', eventTask = 'eventTask';\n var Zone = (function () {\n function Zone(parent, zoneSpec) {\n this._properties = null;\n this._parent = parent;\n this._name = zoneSpec ? zoneSpec.name || 'unnamed' : '';\n this._properties = zoneSpec && zoneSpec.properties || {};\n this._zoneDelegate =\n new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec);\n }\n Zone.assertZonePatched = function () {\n if (global.Promise !== ZoneAwarePromise) {\n throw new Error('Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' +\n 'has been overwritten.\\n' +\n 'Most likely cause is that a Promise polyfill has been loaded ' +\n 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' +\n 'If you must load one, do so before loading zone.js.)');\n }\n };\n Object.defineProperty(Zone, \"root\", {\n get: function () {\n var zone = Zone.current;\n while (zone.parent) {\n zone = zone.parent;\n }\n return zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone, \"current\", {\n get: function () {\n return _currentZoneFrame.zone;\n },\n enumerable: true,\n configurable: true\n });\n \n Object.defineProperty(Zone, \"currentTask\", {\n get: function () {\n return _currentTask;\n },\n enumerable: true,\n configurable: true\n });\n \n Object.defineProperty(Zone.prototype, \"parent\", {\n get: function () {\n return this._parent;\n },\n enumerable: true,\n configurable: true\n });\n \n Object.defineProperty(Zone.prototype, \"name\", {\n get: function () {\n return this._name;\n },\n enumerable: true,\n configurable: true\n });\n \n Zone.prototype.get = function (key) {\n var zone = this.getZoneWith(key);\n if (zone)\n return zone._properties[key];\n };\n Zone.prototype.getZoneWith = function (key) {\n var current = this;\n while (current) {\n if (current._properties.hasOwnProperty(key)) {\n return current;\n }\n current = current._parent;\n }\n return null;\n };\n Zone.prototype.fork = function (zoneSpec) {\n if (!zoneSpec)\n throw new Error('ZoneSpec required!');\n return this._zoneDelegate.fork(this, zoneSpec);\n };\n Zone.prototype.wrap = function (callback, source) {\n if (typeof callback !== 'function') {\n throw new Error('Expecting function got: ' + callback);\n }\n var _callback = this._zoneDelegate.intercept(this, callback, source);\n var zone = this;\n return function () {\n return zone.runGuarded(_callback, this, arguments, source);\n };\n };\n Zone.prototype.run = function (callback, applyThis, applyArgs, source) {\n if (applyThis === void 0) { applyThis = undefined; }\n if (applyArgs === void 0) { applyArgs = null; }\n if (source === void 0) { source = null; }\n _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this);\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runGuarded = function (callback, applyThis, applyArgs, source) {\n if (applyThis === void 0) { applyThis = null; }\n if (applyArgs === void 0) { applyArgs = null; }\n if (source === void 0) { source = null; }\n _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this);\n try {\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runTask = function (task, applyThis, applyArgs) {\n if (task.zone != this)\n throw new Error('A task can only be run in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n var reEntryGuard = task.state != running;\n reEntryGuard && task._transitionTo(running, scheduled);\n task.runCount++;\n var previousTask = _currentTask;\n _currentTask = task;\n _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this);\n try {\n if (task.type == macroTask && task.data && !task.data.isPeriodic) {\n task.cancelFn = null;\n }\n try {\n return this._zoneDelegate.invokeTask(this, task, applyThis, applyArgs);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n // if the task's state is notScheduled or unknown, then it has already been cancelled\n // we should not reset the state to scheduled\n if (task.state !== notScheduled && task.state !== unknown) {\n if (task.type == eventTask || (task.data && task.data.isPeriodic)) {\n reEntryGuard && task._transitionTo(scheduled, running);\n }\n else {\n task.runCount = 0;\n this._updateTaskCount(task, -1);\n reEntryGuard &&\n task._transitionTo(notScheduled, running, notScheduled);\n }\n }\n _currentZoneFrame = _currentZoneFrame.parent;\n _currentTask = previousTask;\n }\n };\n Zone.prototype.scheduleTask = function (task) {\n if (task.zone && task.zone !== this) {\n // check if the task was rescheduled, the newZone\n // should not be the children of the original zone\n var newZone = this;\n while (newZone) {\n if (newZone === task.zone) {\n throw Error(\"can not reschedule task to \" + this\n .name + \" which is descendants of the original zone \" + task.zone.name);\n }\n newZone = newZone.parent;\n }\n }\n task._transitionTo(scheduling, notScheduled);\n var zoneDelegates = [];\n task._zoneDelegates = zoneDelegates;\n task._zone = this;\n try {\n task = this._zoneDelegate.scheduleTask(this, task);\n }\n catch (err) {\n // should set task's state to unknown when scheduleTask throw error\n // because the err may from reschedule, so the fromState maybe notScheduled\n task._transitionTo(unknown, scheduling, notScheduled);\n // TODO: @JiaLiPassion, should we check the result from handleError?\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n if (task._zoneDelegates === zoneDelegates) {\n // we have to check because internally the delegate can reschedule the task.\n this._updateTaskCount(task, 1);\n }\n if (task.state == scheduling) {\n task._transitionTo(scheduled, scheduling);\n }\n return task;\n };\n Zone.prototype.scheduleMicroTask = function (source, callback, data, customSchedule) {\n return this.scheduleTask(new ZoneTask(microTask, source, callback, data, customSchedule, null));\n };\n Zone.prototype.scheduleMacroTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.scheduleEventTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.cancelTask = function (task) {\n if (task.zone != this)\n throw new Error('A task can only be cancelled in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n task._transitionTo(canceling, scheduled, running);\n try {\n this._zoneDelegate.cancelTask(this, task);\n }\n catch (err) {\n // if error occurs when cancelTask, transit the state to unknown\n task._transitionTo(unknown, canceling);\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n this._updateTaskCount(task, -1);\n task._transitionTo(notScheduled, canceling);\n task.runCount = 0;\n return task;\n };\n Zone.prototype._updateTaskCount = function (task, count) {\n var zoneDelegates = task._zoneDelegates;\n if (count == -1) {\n task._zoneDelegates = null;\n }\n for (var i = 0; i < zoneDelegates.length; i++) {\n zoneDelegates[i]._updateTaskCount(task.type, count);\n }\n };\n return Zone;\n }());\n Zone.__symbol__ = __symbol__;\n var DELEGATE_ZS = {\n name: '',\n onHasTask: function (delegate, _, target, hasTaskState) {\n return delegate.hasTask(target, hasTaskState);\n },\n onScheduleTask: function (delegate, _, target, task) {\n return delegate.scheduleTask(target, task);\n },\n onInvokeTask: function (delegate, _, target, task, applyThis, applyArgs) { return delegate.invokeTask(target, task, applyThis, applyArgs); },\n onCancelTask: function (delegate, _, target, task) {\n return delegate.cancelTask(target, task);\n }\n };\n var ZoneDelegate = (function () {\n function ZoneDelegate(zone, parentDelegate, zoneSpec) {\n this._taskCounts = { 'microTask': 0, 'macroTask': 0, 'eventTask': 0 };\n this.zone = zone;\n this._parentDelegate = parentDelegate;\n this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate._forkZS);\n this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate._forkDlgt);\n this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone);\n this._interceptZS =\n zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS);\n this._interceptDlgt =\n zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt);\n this._interceptCurrZone =\n zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone);\n this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS);\n this._invokeDlgt =\n zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt);\n this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone);\n this._handleErrorZS =\n zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS);\n this._handleErrorDlgt =\n zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt);\n this._handleErrorCurrZone =\n zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone);\n this._scheduleTaskZS =\n zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS);\n this._scheduleTaskDlgt =\n zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt);\n this._scheduleTaskCurrZone =\n zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone);\n this._invokeTaskZS =\n zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS);\n this._invokeTaskDlgt =\n zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt);\n this._invokeTaskCurrZone =\n zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone);\n this._cancelTaskZS =\n zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS);\n this._cancelTaskDlgt =\n zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt);\n this._cancelTaskCurrZone =\n zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone);\n this._hasTaskZS = null;\n this._hasTaskDlgt = null;\n this._hasTaskDlgtOwner = null;\n this._hasTaskCurrZone = null;\n var zoneSpecHasTask = zoneSpec && zoneSpec.onHasTask;\n var parentHasTask = parentDelegate && parentDelegate._hasTaskZS;\n if (zoneSpecHasTask || parentHasTask) {\n // If we need to report hasTask, than this ZS needs to do ref counting on tasks. In such\n // a case all task related interceptors must go through this ZD. We can't short circuit it.\n this._hasTaskZS = zoneSpecHasTask ? zoneSpec : DELEGATE_ZS;\n this._hasTaskDlgt = parentDelegate;\n this._hasTaskDlgtOwner = this;\n this._hasTaskCurrZone = zone;\n if (!zoneSpec.onScheduleTask) {\n this._scheduleTaskZS = DELEGATE_ZS;\n this._scheduleTaskDlgt = parentDelegate;\n this._scheduleTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onInvokeTask) {\n this._invokeTaskZS = DELEGATE_ZS;\n this._invokeTaskDlgt = parentDelegate;\n this._invokeTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onCancelTask) {\n this._cancelTaskZS = DELEGATE_ZS;\n this._cancelTaskDlgt = parentDelegate;\n this._cancelTaskCurrZone = this.zone;\n }\n }\n }\n ZoneDelegate.prototype.fork = function (targetZone, zoneSpec) {\n return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) :\n new Zone(targetZone, zoneSpec);\n };\n ZoneDelegate.prototype.intercept = function (targetZone, callback, source) {\n return this._interceptZS ?\n this._interceptZS.onIntercept(this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) :\n callback;\n };\n ZoneDelegate.prototype.invoke = function (targetZone, callback, applyThis, applyArgs, source) {\n return this._invokeZS ?\n this._invokeZS.onInvoke(this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, source) :\n callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.handleError = function (targetZone, error) {\n return this._handleErrorZS ?\n this._handleErrorZS.onHandleError(this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) :\n true;\n };\n ZoneDelegate.prototype.scheduleTask = function (targetZone, task) {\n var returnTask = task;\n if (this._scheduleTaskZS) {\n if (this._hasTaskZS) {\n returnTask._zoneDelegates.push(this._hasTaskDlgtOwner);\n }\n returnTask = this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task);\n if (!returnTask)\n returnTask = task;\n }\n else {\n if (task.scheduleFn) {\n task.scheduleFn(task);\n }\n else if (task.type == microTask) {\n scheduleMicroTask(task);\n }\n else {\n throw new Error('Task is missing scheduleFn.');\n }\n }\n return returnTask;\n };\n ZoneDelegate.prototype.invokeTask = function (targetZone, task, applyThis, applyArgs) {\n return this._invokeTaskZS ?\n this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, applyArgs) :\n task.callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.cancelTask = function (targetZone, task) {\n var value;\n if (this._cancelTaskZS) {\n value = this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task);\n }\n else {\n if (!task.cancelFn) {\n throw Error('Task is not cancelable');\n }\n value = task.cancelFn(task);\n }\n return value;\n };\n ZoneDelegate.prototype.hasTask = function (targetZone, isEmpty) {\n // hasTask should not throw error so other ZoneDelegate\n // can still trigger hasTask callback\n try {\n return this._hasTaskZS &&\n this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty);\n }\n catch (err) {\n }\n };\n ZoneDelegate.prototype._updateTaskCount = function (type, count) {\n var counts = this._taskCounts;\n var prev = counts[type];\n var next = counts[type] = prev + count;\n if (next < 0) {\n throw new Error('More tasks executed then were scheduled.');\n }\n if (prev == 0 || next == 0) {\n var isEmpty = {\n microTask: counts.microTask > 0,\n macroTask: counts.macroTask > 0,\n eventTask: counts.eventTask > 0,\n change: type\n };\n // TODO(misko): what should happen if it throws?\n this.hasTask(this.zone, isEmpty);\n }\n };\n return ZoneDelegate;\n }());\n var ZoneTask = (function () {\n function ZoneTask(type, source, callback, options, scheduleFn, cancelFn) {\n this._zone = null;\n this.runCount = 0;\n this._zoneDelegates = null;\n this._state = 'notScheduled';\n this.type = type;\n this.source = source;\n this.data = options;\n this.scheduleFn = scheduleFn;\n this.cancelFn = cancelFn;\n this.callback = callback;\n var self = this;\n this.invoke = function () {\n _numberOfNestedTaskFrames++;\n try {\n self.runCount++;\n return self.zone.runTask(self, this, arguments);\n }\n finally {\n if (_numberOfNestedTaskFrames == 1) {\n drainMicroTaskQueue();\n }\n _numberOfNestedTaskFrames--;\n }\n };\n }\n Object.defineProperty(ZoneTask.prototype, \"zone\", {\n get: function () {\n return this._zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ZoneTask.prototype, \"state\", {\n get: function () {\n return this._state;\n },\n enumerable: true,\n configurable: true\n });\n ZoneTask.prototype.cancelScheduleRequest = function () {\n this._transitionTo(notScheduled, scheduling);\n };\n ZoneTask.prototype._transitionTo = function (toState, fromState1, fromState2) {\n if (this._state === fromState1 || this._state === fromState2) {\n this._state = toState;\n if (toState == notScheduled) {\n this._zoneDelegates = null;\n }\n }\n else {\n throw new Error(this.type + \" '\" + this.source + \"': can not transition to '\" + toState + \"', expecting state '\" + fromState1 + \"'\" + (fromState2 ?\n ' or \\'' + fromState2 + '\\'' :\n '') + \", was '\" + this._state + \"'.\");\n }\n };\n ZoneTask.prototype.toString = function () {\n if (this.data && typeof this.data.handleId !== 'undefined') {\n return this.data.handleId;\n }\n else {\n return Object.prototype.toString.call(this);\n }\n };\n // add toJSON method to prevent cyclic error when\n // call JSON.stringify(zoneTask)\n ZoneTask.prototype.toJSON = function () {\n return {\n type: this.type,\n state: this.state,\n source: this.source,\n data: this.data,\n zone: this.zone.name,\n invoke: this.invoke,\n scheduleFn: this.scheduleFn,\n cancelFn: this.cancelFn,\n runCount: this.runCount,\n callback: this.callback\n };\n };\n return ZoneTask;\n }());\n var ZoneFrame = (function () {\n function ZoneFrame(parent, zone) {\n this.parent = parent;\n this.zone = zone;\n }\n return ZoneFrame;\n }());\n function __symbol__(name) {\n return '__zone_symbol__' + name;\n }\n \n var symbolSetTimeout = __symbol__('setTimeout');\n var symbolPromise = __symbol__('Promise');\n var symbolThen = __symbol__('then');\n var _currentZoneFrame = new ZoneFrame(null, new Zone(null, null));\n var _currentTask = null;\n var _microTaskQueue = [];\n var _isDrainingMicrotaskQueue = false;\n var _uncaughtPromiseErrors = [];\n var _numberOfNestedTaskFrames = 0;\n function scheduleQueueDrain() {\n // if we are not running in any task, and there has not been anything scheduled\n // we must bootstrap the initial task creation by manually scheduling the drain\n if (_numberOfNestedTaskFrames === 0 && _microTaskQueue.length === 0) {\n // We are not running in Task, so we need to kickstart the microtask queue.\n if (global[symbolPromise]) {\n global[symbolPromise].resolve(0)[symbolThen](drainMicroTaskQueue);\n }\n else {\n global[symbolSetTimeout](drainMicroTaskQueue, 0);\n }\n }\n }\n function scheduleMicroTask(task) {\n scheduleQueueDrain();\n _microTaskQueue.push(task);\n }\n function consoleError(e) {\n if (Zone[__symbol__('ignoreConsoleErrorUncaughtError')]) {\n return;\n }\n var rejection = e && e.rejection;\n if (rejection) {\n console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined);\n }\n console.error(e);\n }\n function handleUnhandledRejection(e) {\n consoleError(e);\n try {\n var handler = Zone[__symbol__('unhandledPromiseRejectionHandler')];\n if (handler && typeof handler === 'function') {\n handler.apply(this, [e]);\n }\n }\n catch (err) {\n }\n }\n function drainMicroTaskQueue() {\n if (!_isDrainingMicrotaskQueue) {\n _isDrainingMicrotaskQueue = true;\n while (_microTaskQueue.length) {\n var queue = _microTaskQueue;\n _microTaskQueue = [];\n for (var i = 0; i < queue.length; i++) {\n var task = queue[i];\n try {\n task.zone.runTask(task, null, null);\n }\n catch (error) {\n consoleError(error);\n }\n }\n }\n while (_uncaughtPromiseErrors.length) {\n var _loop_1 = function () {\n var uncaughtPromiseError = _uncaughtPromiseErrors.shift();\n try {\n uncaughtPromiseError.zone.runGuarded(function () {\n throw uncaughtPromiseError;\n });\n }\n catch (error) {\n handleUnhandledRejection(error);\n }\n };\n while (_uncaughtPromiseErrors.length) {\n _loop_1();\n }\n }\n _isDrainingMicrotaskQueue = false;\n }\n }\n function isThenable(value) {\n return value && value.then;\n }\n function forwardResolution(value) {\n return value;\n }\n function forwardRejection(rejection) {\n return ZoneAwarePromise.reject(rejection);\n }\n var symbolState = __symbol__('state');\n var symbolValue = __symbol__('value');\n var source = 'Promise.then';\n var UNRESOLVED = null;\n var RESOLVED = true;\n var REJECTED = false;\n var REJECTED_NO_CATCH = 0;\n function makeResolver(promise, state) {\n return function (v) {\n try {\n resolvePromise(promise, state, v);\n }\n catch (err) {\n resolvePromise(promise, false, err);\n }\n // Do not return value or you will break the Promise spec.\n };\n }\n var once = function () {\n var wasCalled = false;\n return function wrapper(wrappedFunction) {\n return function () {\n if (wasCalled) {\n return;\n }\n wasCalled = true;\n wrappedFunction.apply(null, arguments);\n };\n };\n };\n // Promise Resolution\n function resolvePromise(promise, state, value) {\n var onceWrapper = once();\n if (promise === value) {\n throw new TypeError('Promise resolved with itself');\n }\n if (promise[symbolState] === UNRESOLVED) {\n // should only get value.then once based on promise spec.\n var then = null;\n try {\n if (typeof value === 'object' || typeof value === 'function') {\n then = value && value.then;\n }\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n return promise;\n }\n // if (value instanceof ZoneAwarePromise) {\n if (state !== REJECTED && value instanceof ZoneAwarePromise &&\n value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) &&\n value[symbolState] !== UNRESOLVED) {\n clearRejectedNoCatch(value);\n resolvePromise(promise, value[symbolState], value[symbolValue]);\n }\n else if (state !== REJECTED && typeof then === 'function') {\n try {\n then.apply(value, [\n onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false))\n ]);\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n }\n }\n else {\n promise[symbolState] = state;\n var queue = promise[symbolValue];\n promise[symbolValue] = value;\n // record task information in value when error occurs, so we can\n // do some additional work such as render longStackTrace\n if (state === REJECTED && value instanceof Error) {\n value[__symbol__('currentTask')] = Zone.currentTask;\n }\n for (var i = 0; i < queue.length;) {\n scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);\n }\n if (queue.length == 0 && state == REJECTED) {\n promise[symbolState] = REJECTED_NO_CATCH;\n try {\n throw new Error('Uncaught (in promise): ' + value +\n (value && value.stack ? '\\n' + value.stack : ''));\n }\n catch (err) {\n var error_1 = err;\n error_1.rejection = value;\n error_1.promise = promise;\n error_1.zone = Zone.current;\n error_1.task = Zone.currentTask;\n _uncaughtPromiseErrors.push(error_1);\n scheduleQueueDrain();\n }\n }\n }\n }\n // Resolving an already resolved promise is a noop.\n return promise;\n }\n function clearRejectedNoCatch(promise) {\n if (promise[symbolState] === REJECTED_NO_CATCH) {\n // if the promise is rejected no catch status\n // and queue.length > 0, means there is a error handler\n // here to handle the rejected promise, we should trigger\n // windows.rejectionhandled eventHandler or nodejs rejectionHandled\n // eventHandler\n try {\n var handler = Zone[__symbol__('rejectionHandledHandler')];\n if (handler && typeof handler === 'function') {\n handler.apply(this, [{ rejection: promise[symbolValue], promise: promise }]);\n }\n }\n catch (err) {\n }\n promise[symbolState] = REJECTED;\n for (var i = 0; i < _uncaughtPromiseErrors.length; i++) {\n if (promise === _uncaughtPromiseErrors[i].promise) {\n _uncaughtPromiseErrors.splice(i, 1);\n }\n }\n }\n }\n function scheduleResolveOrReject(promise, zone, chainPromise, onFulfilled, onRejected) {\n clearRejectedNoCatch(promise);\n var delegate = promise[symbolState] ?\n (typeof onFulfilled === 'function') ? onFulfilled : forwardResolution :\n (typeof onRejected === 'function') ? onRejected : forwardRejection;\n zone.scheduleMicroTask(source, function () {\n try {\n resolvePromise(chainPromise, true, zone.run(delegate, undefined, [promise[symbolValue]]));\n }\n catch (error) {\n resolvePromise(chainPromise, false, error);\n }\n });\n }\n var ZoneAwarePromise = (function () {\n function ZoneAwarePromise(executor) {\n var promise = this;\n if (!(promise instanceof ZoneAwarePromise)) {\n throw new Error('Must be an instanceof Promise.');\n }\n promise[symbolState] = UNRESOLVED;\n promise[symbolValue] = []; // queue;\n try {\n executor && executor(makeResolver(promise, RESOLVED), makeResolver(promise, REJECTED));\n }\n catch (error) {\n resolvePromise(promise, false, error);\n }\n }\n ZoneAwarePromise.toString = function () {\n return 'function ZoneAwarePromise() { [native code] }';\n };\n ZoneAwarePromise.resolve = function (value) {\n return resolvePromise(new this(null), RESOLVED, value);\n };\n ZoneAwarePromise.reject = function (error) {\n return resolvePromise(new this(null), REJECTED, error);\n };\n ZoneAwarePromise.race = function (values) {\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n _a = [res, rej], resolve = _a[0], reject = _a[1];\n var _a;\n });\n function onResolve(value) {\n promise && (promise = null || resolve(value));\n }\n function onReject(error) {\n promise && (promise = null || reject(error));\n }\n for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {\n var value = values_1[_i];\n if (!isThenable(value)) {\n value = this.resolve(value);\n }\n value.then(onResolve, onReject);\n }\n return promise;\n };\n ZoneAwarePromise.all = function (values) {\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n resolve = res;\n reject = rej;\n });\n var count = 0;\n var resolvedValues = [];\n for (var _i = 0, values_2 = values; _i < values_2.length; _i++) {\n var value = values_2[_i];\n if (!isThenable(value)) {\n value = this.resolve(value);\n }\n value.then((function (index) { return function (value) {\n resolvedValues[index] = value;\n count--;\n if (!count) {\n resolve(resolvedValues);\n }\n }; })(count), reject);\n count++;\n }\n if (!count)\n resolve(resolvedValues);\n return promise;\n };\n ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) {\n var chainPromise = new this.constructor(null);\n var zone = Zone.current;\n if (this[symbolState] == UNRESOLVED) {\n this[symbolValue].push(zone, chainPromise, onFulfilled, onRejected);\n }\n else {\n scheduleResolveOrReject(this, zone, chainPromise, onFulfilled, onRejected);\n }\n return chainPromise;\n };\n ZoneAwarePromise.prototype.catch = function (onRejected) {\n return this.then(null, onRejected);\n };\n return ZoneAwarePromise;\n }());\n // Protect against aggressive optimizers dropping seemingly unused properties.\n // E.g. Closure Compiler in advanced mode.\n ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve;\n ZoneAwarePromise['reject'] = ZoneAwarePromise.reject;\n ZoneAwarePromise['race'] = ZoneAwarePromise.race;\n ZoneAwarePromise['all'] = ZoneAwarePromise.all;\n var NativePromise = global[symbolPromise] = global['Promise'];\n global['Promise'] = ZoneAwarePromise;\n var symbolThenPatched = __symbol__('thenPatched');\n function patchThen(Ctor) {\n var proto = Ctor.prototype;\n var originalThen = proto.then;\n // Keep a reference to the original method.\n proto[symbolThen] = originalThen;\n Ctor.prototype.then = function (onResolve, onReject) {\n var _this = this;\n var wrapped = new ZoneAwarePromise(function (resolve, reject) {\n originalThen.call(_this, resolve, reject);\n });\n return wrapped.then(onResolve, onReject);\n };\n Ctor[symbolThenPatched] = true;\n }\n function zoneify(fn) {\n return function () {\n var resultPromise = fn.apply(this, arguments);\n if (resultPromise instanceof ZoneAwarePromise) {\n return resultPromise;\n }\n var Ctor = resultPromise.constructor;\n if (!Ctor[symbolThenPatched]) {\n patchThen(Ctor);\n }\n return resultPromise;\n };\n }\n if (NativePromise) {\n patchThen(NativePromise);\n var fetch_1 = global['fetch'];\n if (typeof fetch_1 == 'function') {\n global['fetch'] = zoneify(fetch_1);\n }\n }\n // This is not part of public API, but it is usefull for tests, so we expose it.\n Promise[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors;\n var blacklistedStackFramesSymbol = Zone.__symbol__('blacklistedStackFrames');\n var NativeError = global[__symbol__('Error')] = global.Error;\n // Store the frames which should be removed from the stack frames\n var blackListedStackFrames = {};\n // We must find the frame where Error was created, otherwise we assume we don't understand stack\n var zoneAwareFrame1;\n var zoneAwareFrame2;\n global.Error = ZoneAwareError;\n var stackRewrite = 'stackRewrite';\n /**\n * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as\n * adds zone information to it.\n */\n function ZoneAwareError() {\n var _this = this;\n // We always have to return native error otherwise the browser console will not work.\n var error = NativeError.apply(this, arguments);\n if (!error.stack) {\n // in IE, the error.stack will be undefined\n // when error was constructed, it will only\n // be available when throw\n try {\n throw error;\n }\n catch (err) {\n error = err;\n }\n }\n // Save original stack trace\n var originalStack = error['originalStack'] = error.stack;\n // Process the stack trace and rewrite the frames.\n if (ZoneAwareError[stackRewrite] && originalStack) {\n var frames_1 = originalStack.split('\\n');\n var zoneFrame = _currentZoneFrame;\n var i = 0;\n // Find the first frame\n while (!(frames_1[i] === zoneAwareFrame1 || frames_1[i] === zoneAwareFrame2) &&\n i < frames_1.length) {\n i++;\n }\n for (; i < frames_1.length && zoneFrame; i++) {\n var frame = frames_1[i];\n if (frame.trim()) {\n switch (blackListedStackFrames[frame]) {\n case 0 /* blackList */:\n frames_1.splice(i, 1);\n i--;\n break;\n case 1 /* transition */:\n if (zoneFrame.parent) {\n // This is the special frame where zone changed. Print and process it accordingly\n frames_1[i] += \" [\" + zoneFrame.parent.zone.name + \" => \" + zoneFrame.zone.name + \"]\";\n zoneFrame = zoneFrame.parent;\n }\n else {\n zoneFrame = null;\n }\n break;\n default:\n frames_1[i] += \" [\" + zoneFrame.zone.name + \"]\";\n }\n }\n }\n try {\n error.stack = error.zoneAwareStack = frames_1.join('\\n');\n }\n catch (e) {\n // ignore as some browsers don't allow overriding of stack\n }\n }\n if (this instanceof NativeError && this.constructor != NativeError) {\n // We got called with a `new` operator AND we are subclass of ZoneAwareError\n // in that case we have to copy all of our properties to `this`.\n Object.keys(error).concat('stack', 'message').forEach(function (key) {\n if (error[key] !== undefined) {\n try {\n _this[key] = error[key];\n }\n catch (e) {\n // ignore the assignment in case it is a setter and it throws.\n }\n }\n });\n return this;\n }\n return error;\n }\n // Copy the prototype so that instanceof operator works as expected\n ZoneAwareError.prototype = NativeError.prototype;\n ZoneAwareError[blacklistedStackFramesSymbol] = blackListedStackFrames;\n ZoneAwareError[stackRewrite] = false;\n // those properties need special handling\n var specialPropertyNames = ['stackTraceLimit', 'captureStackTrace', 'prepareStackTrace'];\n // those properties of NativeError should be set to ZoneAwareError\n var nativeErrorProperties = Object.keys(NativeError);\n if (nativeErrorProperties) {\n nativeErrorProperties.forEach(function (prop) {\n if (specialPropertyNames.filter(function (sp) { return sp === prop; }).length === 0) {\n Object.defineProperty(ZoneAwareError, prop, {\n get: function () {\n return NativeError[prop];\n },\n set: function (value) {\n NativeError[prop] = value;\n }\n });\n }\n });\n }\n if (NativeError.hasOwnProperty('stackTraceLimit')) {\n // Extend default stack limit as we will be removing few frames.\n NativeError.stackTraceLimit = Math.max(NativeError.stackTraceLimit, 15);\n // make sure that ZoneAwareError has the same property which forwards to NativeError.\n Object.defineProperty(ZoneAwareError, 'stackTraceLimit', {\n get: function () {\n return NativeError.stackTraceLimit;\n },\n set: function (value) {\n return NativeError.stackTraceLimit = value;\n }\n });\n }\n if (NativeError.hasOwnProperty('captureStackTrace')) {\n Object.defineProperty(ZoneAwareError, 'captureStackTrace', {\n // add named function here because we need to remove this\n // stack frame when prepareStackTrace below\n value: function zoneCaptureStackTrace(targetObject, constructorOpt) {\n NativeError.captureStackTrace(targetObject, constructorOpt);\n }\n });\n }\n Object.defineProperty(ZoneAwareError, 'prepareStackTrace', {\n get: function () {\n return NativeError.prepareStackTrace;\n },\n set: function (value) {\n if (!value || typeof value !== 'function') {\n return NativeError.prepareStackTrace = value;\n }\n return NativeError.prepareStackTrace = function (error, structuredStackTrace) {\n // remove additional stack information from ZoneAwareError.captureStackTrace\n if (structuredStackTrace) {\n for (var i = 0; i < structuredStackTrace.length; i++) {\n var st = structuredStackTrace[i];\n // remove the first function which name is zoneCaptureStackTrace\n if (st.getFunctionName() === 'zoneCaptureStackTrace') {\n structuredStackTrace.splice(i, 1);\n break;\n }\n }\n }\n return value.apply(this, [error, structuredStackTrace]);\n };\n }\n });\n // Now we need to populate the `blacklistedStackFrames` as well as find the\n // run/runGuraded/runTask frames. This is done by creating a detect zone and then threading\n // the execution through all of the above methods so that we can look at the stack trace and\n // find the frames of interest.\n var detectZone = Zone.current.fork({\n name: 'detect',\n onInvoke: function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) {\n // Here only so that it will show up in the stack frame so that it can be black listed.\n return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source);\n },\n onHandleError: function (parentZD, current, target, error) {\n if (error.originalStack && Error === ZoneAwareError) {\n var frames_2 = error.originalStack.split(/\\n/);\n var runFrame = false, runGuardedFrame = false, runTaskFrame = false;\n while (frames_2.length) {\n var frame = frames_2.shift();\n // On safari it is possible to have stack frame with no line number.\n // This check makes sure that we don't filter frames on name only (must have\n // linenumber)\n if (/:\\d+:\\d+/.test(frame)) {\n // Get rid of the path so that we don't accidentally find function name in path.\n // In chrome the separator is `(` and `@` in FF and safari\n // Chrome: at Zone.run (zone.js:100)\n // Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24)\n // FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24\n // Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24\n var fnName = frame.split('(')[0].split('@')[0];\n var frameType = 1;\n if (fnName.indexOf('ZoneAwareError') !== -1) {\n zoneAwareFrame1 = frame;\n zoneAwareFrame2 = frame.replace('Error.', '');\n blackListedStackFrames[zoneAwareFrame2] = 0 /* blackList */;\n }\n if (fnName.indexOf('runGuarded') !== -1) {\n runGuardedFrame = true;\n }\n else if (fnName.indexOf('runTask') !== -1) {\n runTaskFrame = true;\n }\n else if (fnName.indexOf('run') !== -1) {\n runFrame = true;\n }\n else {\n frameType = 0 /* blackList */;\n }\n blackListedStackFrames[frame] = frameType;\n // Once we find all of the frames we can stop looking.\n if (runFrame && runGuardedFrame && runTaskFrame) {\n ZoneAwareError[stackRewrite] = true;\n break;\n }\n }\n }\n }\n return false;\n }\n });\n // carefully constructor a stack frame which contains all of the frames of interest which\n // need to be detected and blacklisted.\n // carefully constructor a stack frame which contains all of the frames of interest which\n // need to be detected and blacklisted.\n var detectRunFn = function () {\n detectZone.run(function () {\n detectZone.runGuarded(function () {\n throw new ZoneAwareError(ZoneAwareError, NativeError);\n });\n });\n };\n // Cause the error to extract the stack frames.\n detectZone.runTask(detectZone.scheduleMacroTask('detect', detectRunFn, null, function () { return null; }, null));\n return global['Zone'] = Zone;\n})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * Suppress closure compiler errors about unknown 'Zone' variable\n * @fileoverview\n * @suppress {undefinedVars,globalThis}\n */\nvar zoneSymbol = function (n) { return \"__zone_symbol__\" + n; };\nvar _global$1 = typeof window === 'object' && window || typeof self === 'object' && self || global;\nfunction bindArguments(args, source) {\n for (var i = args.length - 1; i >= 0; i--) {\n if (typeof args[i] === 'function') {\n args[i] = Zone.current.wrap(args[i], source + '_' + i);\n }\n }\n return args;\n}\nfunction patchPrototype(prototype, fnNames) {\n var source = prototype.constructor['name'];\n var _loop_1 = function (i) {\n var name_1 = fnNames[i];\n var delegate = prototype[name_1];\n if (delegate) {\n prototype[name_1] = (function (delegate) {\n return function () {\n return delegate.apply(this, bindArguments(arguments, source + '.' + name_1));\n };\n })(delegate);\n }\n };\n for (var i = 0; i < fnNames.length; i++) {\n _loop_1(i);\n }\n}\nvar isWebWorker = (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope);\nvar isNode = (!('nw' in _global$1) && typeof process !== 'undefined' &&\n {}.toString.call(process) === '[object process]');\nvar isBrowser = !isNode && !isWebWorker && !!(typeof window !== 'undefined' && window['HTMLElement']);\n// we are in electron of nw, so we are both browser and nodejs\nvar isMix = typeof process !== 'undefined' &&\n {}.toString.call(process) === '[object process]' && !isWebWorker &&\n !!(typeof window !== 'undefined' && window['HTMLElement']);\nfunction patchProperty(obj, prop) {\n var desc = Object.getOwnPropertyDescriptor(obj, prop) || { enumerable: true, configurable: true };\n var originalDesc = Object.getOwnPropertyDescriptor(obj, 'original' + prop);\n if (!originalDesc && desc.get) {\n Object.defineProperty(obj, 'original' + prop, { enumerable: false, configurable: true, get: desc.get });\n }\n // A property descriptor cannot have getter/setter and be writable\n // deleting the writable and value properties avoids this error:\n //\n // TypeError: property descriptors must not specify a value or be writable when a\n // getter or setter has been specified\n delete desc.writable;\n delete desc.value;\n // substr(2) cuz 'onclick' -> 'click', etc\n var eventName = prop.substr(2);\n var _prop = zoneSymbol('_' + prop);\n desc.set = function (fn) {\n if (this[_prop]) {\n this.removeEventListener(eventName, this[_prop]);\n }\n if (typeof fn === 'function') {\n var wrapFn = function (event) {\n var result;\n result = fn.apply(this, arguments);\n if (result != undefined && !result) {\n event.preventDefault();\n }\n return result;\n };\n this[_prop] = wrapFn;\n this.addEventListener(eventName, wrapFn, false);\n }\n else {\n this[_prop] = null;\n }\n };\n // The getter would return undefined for unassigned properties but the default value of an\n // unassigned property is null\n desc.get = function () {\n var r = this[_prop] || null;\n // result will be null when use inline event attribute,\n // such as \n // because the onclick function is internal raw uncompiled handler\n // the onclick will be evaluated when first time event was triggered or\n // the property is accessed, https://github.com/angular/zone.js/issues/525\n // so we should use original native get to retrieve the handler\n if (r === null) {\n if (originalDesc && originalDesc.get) {\n r = originalDesc.get.apply(this, arguments);\n if (r) {\n desc.set.apply(this, [r]);\n if (typeof this['removeAttribute'] === 'function') {\n this.removeAttribute(prop);\n }\n }\n }\n }\n return this[_prop] || null;\n };\n Object.defineProperty(obj, prop, desc);\n}\n\nfunction patchOnProperties(obj, properties) {\n var onProperties = [];\n for (var prop in obj) {\n if (prop.substr(0, 2) == 'on') {\n onProperties.push(prop);\n }\n }\n for (var j = 0; j < onProperties.length; j++) {\n patchProperty(obj, onProperties[j]);\n }\n if (properties) {\n for (var i = 0; i < properties.length; i++) {\n patchProperty(obj, 'on' + properties[i]);\n }\n }\n}\n\nvar EVENT_TASKS = zoneSymbol('eventTasks');\n// For EventTarget\nvar ADD_EVENT_LISTENER = 'addEventListener';\nvar REMOVE_EVENT_LISTENER = 'removeEventListener';\nfunction findExistingRegisteredTask(target, handler, name, capture, remove) {\n var eventTasks = target[EVENT_TASKS];\n if (eventTasks) {\n for (var i = 0; i < eventTasks.length; i++) {\n var eventTask = eventTasks[i];\n var data = eventTask.data;\n var listener = data.handler;\n if ((data.handler === handler || listener.listener === handler) &&\n data.useCapturing === capture && data.eventName === name) {\n if (remove) {\n eventTasks.splice(i, 1);\n }\n return eventTask;\n }\n }\n }\n return null;\n}\nfunction attachRegisteredEvent(target, eventTask, isPrepend) {\n var eventTasks = target[EVENT_TASKS];\n if (!eventTasks) {\n eventTasks = target[EVENT_TASKS] = [];\n }\n if (isPrepend) {\n eventTasks.unshift(eventTask);\n }\n else {\n eventTasks.push(eventTask);\n }\n}\nvar defaultListenerMetaCreator = function (self, args) {\n return {\n useCapturing: args[2],\n eventName: args[0],\n handler: args[1],\n target: self || _global$1,\n name: args[0],\n invokeAddFunc: function (addFnSymbol, delegate) {\n if (delegate && delegate.invoke) {\n return this.target[addFnSymbol](this.eventName, delegate.invoke, this.useCapturing);\n }\n else {\n return this.target[addFnSymbol](this.eventName, delegate, this.useCapturing);\n }\n },\n invokeRemoveFunc: function (removeFnSymbol, delegate) {\n if (delegate && delegate.invoke) {\n return this.target[removeFnSymbol](this.eventName, delegate.invoke, this.useCapturing);\n }\n else {\n return this.target[removeFnSymbol](this.eventName, delegate, this.useCapturing);\n }\n }\n };\n};\nfunction makeZoneAwareAddListener(addFnName, removeFnName, useCapturingParam, allowDuplicates, isPrepend, metaCreator) {\n if (useCapturingParam === void 0) { useCapturingParam = true; }\n if (allowDuplicates === void 0) { allowDuplicates = false; }\n if (isPrepend === void 0) { isPrepend = false; }\n if (metaCreator === void 0) { metaCreator = defaultListenerMetaCreator; }\n var addFnSymbol = zoneSymbol(addFnName);\n var removeFnSymbol = zoneSymbol(removeFnName);\n var defaultUseCapturing = useCapturingParam ? false : undefined;\n function scheduleEventListener(eventTask) {\n var meta = eventTask.data;\n attachRegisteredEvent(meta.target, eventTask, isPrepend);\n return meta.invokeAddFunc(addFnSymbol, eventTask);\n }\n function cancelEventListener(eventTask) {\n var meta = eventTask.data;\n findExistingRegisteredTask(meta.target, eventTask.invoke, meta.eventName, meta.useCapturing, true);\n return meta.invokeRemoveFunc(removeFnSymbol, eventTask);\n }\n return function zoneAwareAddListener(self, args) {\n var data = metaCreator(self, args);\n data.useCapturing = data.useCapturing || defaultUseCapturing;\n // - Inside a Web Worker, `this` is undefined, the context is `global`\n // - When `addEventListener` is called on the global context in strict mode, `this` is undefined\n // see https://github.com/angular/zone.js/issues/190\n var delegate = null;\n if (typeof data.handler == 'function') {\n delegate = data.handler;\n }\n else if (data.handler && data.handler.handleEvent) {\n delegate = function (event) { return data.handler.handleEvent(event); };\n }\n var validZoneHandler = false;\n try {\n // In cross site contexts (such as WebDriver frameworks like Selenium),\n // accessing the handler object here will cause an exception to be thrown which\n // will fail tests prematurely.\n validZoneHandler = data.handler && data.handler.toString() === '[object FunctionWrapper]';\n }\n catch (error) {\n // Returning nothing here is fine, because objects in a cross-site context are unusable\n return;\n }\n // Ignore special listeners of IE11 & Edge dev tools, see\n // https://github.com/angular/zone.js/issues/150\n if (!delegate || validZoneHandler) {\n return data.invokeAddFunc(addFnSymbol, data.handler);\n }\n if (!allowDuplicates) {\n var eventTask = findExistingRegisteredTask(data.target, data.handler, data.eventName, data.useCapturing, false);\n if (eventTask) {\n // we already registered, so this will have noop.\n return data.invokeAddFunc(addFnSymbol, eventTask);\n }\n }\n var zone = Zone.current;\n var source = data.target.constructor['name'] + '.' + addFnName + ':' + data.eventName;\n zone.scheduleEventTask(source, delegate, data, scheduleEventListener, cancelEventListener);\n };\n}\nfunction makeZoneAwareRemoveListener(fnName, useCapturingParam, metaCreator) {\n if (useCapturingParam === void 0) { useCapturingParam = true; }\n if (metaCreator === void 0) { metaCreator = defaultListenerMetaCreator; }\n var symbol = zoneSymbol(fnName);\n var defaultUseCapturing = useCapturingParam ? false : undefined;\n return function zoneAwareRemoveListener(self, args) {\n var data = metaCreator(self, args);\n data.useCapturing = data.useCapturing || defaultUseCapturing;\n // - Inside a Web Worker, `this` is undefined, the context is `global`\n // - When `addEventListener` is called on the global context in strict mode, `this` is undefined\n // see https://github.com/angular/zone.js/issues/190\n var eventTask = findExistingRegisteredTask(data.target, data.handler, data.eventName, data.useCapturing, true);\n if (eventTask) {\n eventTask.zone.cancelTask(eventTask);\n }\n else {\n data.invokeRemoveFunc(symbol, data.handler);\n }\n };\n}\n\n\nvar zoneAwareAddEventListener = makeZoneAwareAddListener(ADD_EVENT_LISTENER, REMOVE_EVENT_LISTENER);\nvar zoneAwareRemoveEventListener = makeZoneAwareRemoveListener(REMOVE_EVENT_LISTENER);\nfunction patchEventTargetMethods(obj, addFnName, removeFnName, metaCreator) {\n if (addFnName === void 0) { addFnName = ADD_EVENT_LISTENER; }\n if (removeFnName === void 0) { removeFnName = REMOVE_EVENT_LISTENER; }\n if (metaCreator === void 0) { metaCreator = defaultListenerMetaCreator; }\n if (obj && obj[addFnName]) {\n patchMethod(obj, addFnName, function () { return makeZoneAwareAddListener(addFnName, removeFnName, true, false, false, metaCreator); });\n patchMethod(obj, removeFnName, function () { return makeZoneAwareRemoveListener(removeFnName, true, metaCreator); });\n return true;\n }\n else {\n return false;\n }\n}\nvar originalInstanceKey = zoneSymbol('originalInstance');\n// wrap some native API on `window`\nfunction patchClass(className) {\n var OriginalClass = _global$1[className];\n if (!OriginalClass)\n return;\n _global$1[className] = function () {\n var a = bindArguments(arguments, className);\n switch (a.length) {\n case 0:\n this[originalInstanceKey] = new OriginalClass();\n break;\n case 1:\n this[originalInstanceKey] = new OriginalClass(a[0]);\n break;\n case 2:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1]);\n break;\n case 3:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]);\n break;\n case 4:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]);\n break;\n default:\n throw new Error('Arg list too long.');\n }\n };\n var instance = new OriginalClass(function () { });\n var prop;\n for (prop in instance) {\n // https://bugs.webkit.org/show_bug.cgi?id=44721\n if (className === 'XMLHttpRequest' && prop === 'responseBlob')\n continue;\n (function (prop) {\n if (typeof instance[prop] === 'function') {\n _global$1[className].prototype[prop] = function () {\n return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments);\n };\n }\n else {\n Object.defineProperty(_global$1[className].prototype, prop, {\n set: function (fn) {\n if (typeof fn === 'function') {\n this[originalInstanceKey][prop] = Zone.current.wrap(fn, className + '.' + prop);\n }\n else {\n this[originalInstanceKey][prop] = fn;\n }\n },\n get: function () {\n return this[originalInstanceKey][prop];\n }\n });\n }\n }(prop));\n }\n for (prop in OriginalClass) {\n if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) {\n _global$1[className][prop] = OriginalClass[prop];\n }\n }\n}\n\nfunction createNamedFn(name, delegate) {\n try {\n return (Function('f', \"return function \" + name + \"(){return f(this, arguments)}\"))(delegate);\n }\n catch (error) {\n // if we fail, we must be CSP, just return delegate.\n return function () {\n return delegate(this, arguments);\n };\n }\n}\nfunction patchMethod(target, name, patchFn) {\n var proto = target;\n while (proto && Object.getOwnPropertyNames(proto).indexOf(name) === -1) {\n proto = Object.getPrototypeOf(proto);\n }\n if (!proto && target[name]) {\n // somehow we did not find it, but we can see it. This happens on IE for Window properties.\n proto = target;\n }\n var delegateName = zoneSymbol(name);\n var delegate;\n if (proto && !(delegate = proto[delegateName])) {\n delegate = proto[delegateName] = proto[name];\n proto[name] = createNamedFn(name, patchFn(delegate, delegateName, name));\n }\n return delegate;\n}\n// TODO: @JiaLiPassion, support cancel task later if necessary\n\n\nfunction findEventTask(target, evtName) {\n var eventTasks = target[zoneSymbol('eventTasks')];\n var result = [];\n if (eventTasks) {\n for (var i = 0; i < eventTasks.length; i++) {\n var eventTask = eventTasks[i];\n var data = eventTask.data;\n var eventName = data && data.eventName;\n if (eventName === evtName) {\n result.push(eventTask);\n }\n }\n }\n return result;\n}\nZone[zoneSymbol('patchEventTargetMethods')] = patchEventTargetMethods;\nZone[zoneSymbol('patchOnProperties')] = patchOnProperties;\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction patchTimer(window, setName, cancelName, nameSuffix) {\n var setNative = null;\n var clearNative = null;\n setName += nameSuffix;\n cancelName += nameSuffix;\n var tasksByHandleId = {};\n function scheduleTask(task) {\n var data = task.data;\n function timer() {\n try {\n task.invoke.apply(this, arguments);\n }\n finally {\n delete tasksByHandleId[data.handleId];\n }\n }\n \n data.args[0] = timer;\n data.handleId = setNative.apply(window, data.args);\n tasksByHandleId[data.handleId] = task;\n return task;\n }\n function clearTask(task) {\n delete tasksByHandleId[task.data.handleId];\n return clearNative(task.data.handleId);\n }\n setNative =\n patchMethod(window, setName, function (delegate) { return function (self, args) {\n if (typeof args[0] === 'function') {\n var zone = Zone.current;\n var options = {\n handleId: null,\n isPeriodic: nameSuffix === 'Interval',\n delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 : null,\n args: args\n };\n var task = zone.scheduleMacroTask(setName, args[0], options, scheduleTask, clearTask);\n if (!task) {\n return task;\n }\n // Node.js must additionally support the ref and unref functions.\n var handle = task.data.handleId;\n // check whether handle is null, because some polyfill or browser\n // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame\n if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' &&\n typeof handle.unref === 'function') {\n task.ref = handle.ref.bind(handle);\n task.unref = handle.unref.bind(handle);\n }\n return task;\n }\n else {\n // cause an error by calling it directly.\n return delegate.apply(window, args);\n }\n }; });\n clearNative =\n patchMethod(window, cancelName, function (delegate) { return function (self, args) {\n var task = typeof args[0] === 'number' ? tasksByHandleId[args[0]] : args[0];\n if (task && typeof task.type === 'string') {\n if (task.state !== 'notScheduled' &&\n (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) {\n // Do not cancel already canceled functions\n task.zone.cancelTask(task);\n }\n }\n else {\n // cause an error by calling it directly.\n delegate.apply(window, args);\n }\n }; });\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/*\n * This is necessary for Chrome and Chrome mobile, to enable\n * things like redefining `createdCallback` on an element.\n */\nvar _defineProperty = Object[zoneSymbol('defineProperty')] = Object.defineProperty;\nvar _getOwnPropertyDescriptor = Object[zoneSymbol('getOwnPropertyDescriptor')] =\n Object.getOwnPropertyDescriptor;\nvar _create = Object.create;\nvar unconfigurablesKey = zoneSymbol('unconfigurables');\nfunction propertyPatch() {\n Object.defineProperty = function (obj, prop, desc) {\n if (isUnconfigurable(obj, prop)) {\n throw new TypeError('Cannot assign to read only property \\'' + prop + '\\' of ' + obj);\n }\n var originalConfigurableFlag = desc.configurable;\n if (prop !== 'prototype') {\n desc = rewriteDescriptor(obj, prop, desc);\n }\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n };\n Object.defineProperties = function (obj, props) {\n Object.keys(props).forEach(function (prop) {\n Object.defineProperty(obj, prop, props[prop]);\n });\n return obj;\n };\n Object.create = function (obj, proto) {\n if (typeof proto === 'object' && !Object.isFrozen(proto)) {\n Object.keys(proto).forEach(function (prop) {\n proto[prop] = rewriteDescriptor(obj, prop, proto[prop]);\n });\n }\n return _create(obj, proto);\n };\n Object.getOwnPropertyDescriptor = function (obj, prop) {\n var desc = _getOwnPropertyDescriptor(obj, prop);\n if (isUnconfigurable(obj, prop)) {\n desc.configurable = false;\n }\n return desc;\n };\n}\n\nfunction _redefineProperty(obj, prop, desc) {\n var originalConfigurableFlag = desc.configurable;\n desc = rewriteDescriptor(obj, prop, desc);\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n}\n\nfunction isUnconfigurable(obj, prop) {\n return obj && obj[unconfigurablesKey] && obj[unconfigurablesKey][prop];\n}\nfunction rewriteDescriptor(obj, prop, desc) {\n desc.configurable = true;\n if (!desc.configurable) {\n if (!obj[unconfigurablesKey]) {\n _defineProperty(obj, unconfigurablesKey, { writable: true, value: {} });\n }\n obj[unconfigurablesKey][prop] = true;\n }\n return desc;\n}\nfunction _tryDefineProperty(obj, prop, desc, originalConfigurableFlag) {\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n if (desc.configurable) {\n // In case of errors, when the configurable flag was likely set by rewriteDescriptor(), let's\n // retry with the original flag value\n if (typeof originalConfigurableFlag == 'undefined') {\n delete desc.configurable;\n }\n else {\n desc.configurable = originalConfigurableFlag;\n }\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n var descJson = null;\n try {\n descJson = JSON.stringify(desc);\n }\n catch (error) {\n descJson = descJson.toString();\n }\n console.log(\"Attempting to configure '\" + prop + \"' with descriptor '\" + descJson + \"' on object '\" + obj + \"' and got error, giving up: \" + error);\n }\n }\n else {\n throw error;\n }\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar WTF_ISSUE_555 = 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video';\nvar NO_EVENT_TARGET = 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket'\n .split(',');\nvar EVENT_TARGET = 'EventTarget';\nfunction eventTargetPatch(_global) {\n var apis = [];\n var isWtf = _global['wtf'];\n if (isWtf) {\n // Workaround for: https://github.com/google/tracing-framework/issues/555\n apis = WTF_ISSUE_555.split(',').map(function (v) { return 'HTML' + v + 'Element'; }).concat(NO_EVENT_TARGET);\n }\n else if (_global[EVENT_TARGET]) {\n apis.push(EVENT_TARGET);\n }\n else {\n // Note: EventTarget is not available in all browsers,\n // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget\n apis = NO_EVENT_TARGET;\n }\n for (var i = 0; i < apis.length; i++) {\n var type = _global[apis[i]];\n patchEventTargetMethods(type && type.prototype);\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// we have to patch the instance since the proto is non-configurable\nfunction apply(_global) {\n var WS = _global.WebSocket;\n // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener\n // On older Chrome, no need since EventTarget was already patched\n if (!_global.EventTarget) {\n patchEventTargetMethods(WS.prototype);\n }\n _global.WebSocket = function (a, b) {\n var socket = arguments.length > 1 ? new WS(a, b) : new WS(a);\n var proxySocket;\n // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance\n var onmessageDesc = Object.getOwnPropertyDescriptor(socket, 'onmessage');\n if (onmessageDesc && onmessageDesc.configurable === false) {\n proxySocket = Object.create(socket);\n ['addEventListener', 'removeEventListener', 'send', 'close'].forEach(function (propName) {\n proxySocket[propName] = function () {\n return socket[propName].apply(socket, arguments);\n };\n });\n }\n else {\n // we can patch the real socket\n proxySocket = socket;\n }\n patchOnProperties(proxySocket, ['close', 'error', 'message', 'open']);\n return proxySocket;\n };\n for (var prop in WS) {\n _global.WebSocket[prop] = WS[prop];\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar eventNames = 'copy cut paste abort blur focus canplay canplaythrough change click contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop durationchange emptied ended input invalid keydown keypress keyup load loadeddata loadedmetadata loadstart message mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup pause play playing progress ratechange reset scroll seeked seeking select show stalled submit suspend timeupdate volumechange waiting mozfullscreenchange mozfullscreenerror mozpointerlockchange mozpointerlockerror error webglcontextrestored webglcontextlost webglcontextcreationerror'\n .split(' ');\nfunction propertyDescriptorPatch(_global) {\n if (isNode && !isMix) {\n return;\n }\n var supportsWebSocket = typeof WebSocket !== 'undefined';\n if (canPatchViaPropertyDescriptor()) {\n // for browsers that we can patch the descriptor: Chrome & Firefox\n if (isBrowser) {\n patchOnProperties(window, eventNames);\n patchOnProperties(Document.prototype, eventNames);\n if (typeof SVGElement !== 'undefined') {\n patchOnProperties(SVGElement.prototype, eventNames);\n }\n patchOnProperties(HTMLElement.prototype, eventNames);\n }\n patchOnProperties(XMLHttpRequest.prototype, null);\n if (typeof IDBIndex !== 'undefined') {\n patchOnProperties(IDBIndex.prototype, null);\n patchOnProperties(IDBRequest.prototype, null);\n patchOnProperties(IDBOpenDBRequest.prototype, null);\n patchOnProperties(IDBDatabase.prototype, null);\n patchOnProperties(IDBTransaction.prototype, null);\n patchOnProperties(IDBCursor.prototype, null);\n }\n if (supportsWebSocket) {\n patchOnProperties(WebSocket.prototype, null);\n }\n }\n else {\n // Safari, Android browsers (Jelly Bean)\n patchViaCapturingAllTheEvents();\n patchClass('XMLHttpRequest');\n if (supportsWebSocket) {\n apply(_global);\n }\n }\n}\nfunction canPatchViaPropertyDescriptor() {\n if ((isBrowser || isMix) && !Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') &&\n typeof Element !== 'undefined') {\n // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364\n // IDL interface attributes are not configurable\n var desc = Object.getOwnPropertyDescriptor(Element.prototype, 'onclick');\n if (desc && !desc.configurable)\n return false;\n }\n var xhrDesc = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'onreadystatechange');\n // add enumerable and configurable here because in opera\n // by default XMLHttpRequest.prototype.onreadystatechange is undefined\n // without adding enumerable and configurable will cause onreadystatechange\n // non-configurable\n Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', {\n enumerable: true,\n configurable: true,\n get: function () {\n return true;\n }\n });\n var req = new XMLHttpRequest();\n var result = !!req.onreadystatechange;\n // restore original desc\n Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});\n return result;\n}\n\nvar unboundKey = zoneSymbol('unbound');\n// Whenever any eventListener fires, we check the eventListener target and all parents\n// for `onwhatever` properties and replace them with zone-bound functions\n// - Chrome (for now)\nfunction patchViaCapturingAllTheEvents() {\n var _loop_1 = function (i) {\n var property = eventNames[i];\n var onproperty = 'on' + property;\n self.addEventListener(property, function (event) {\n var elt = event.target, bound, source;\n if (elt) {\n source = elt.constructor['name'] + '.' + onproperty;\n }\n else {\n source = 'unknown.' + onproperty;\n }\n while (elt) {\n if (elt[onproperty] && !elt[onproperty][unboundKey]) {\n bound = Zone.current.wrap(elt[onproperty], source);\n bound[unboundKey] = elt[onproperty];\n elt[onproperty] = bound;\n }\n elt = elt.parentElement;\n }\n }, true);\n };\n for (var i = 0; i < eventNames.length; i++) {\n _loop_1(i);\n }\n \n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction registerElementPatch(_global) {\n if ((!isBrowser && !isMix) || !('registerElement' in _global.document)) {\n return;\n }\n var _registerElement = document.registerElement;\n var callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];\n document.registerElement = function (name, opts) {\n if (opts && opts.prototype) {\n callbacks.forEach(function (callback) {\n var source = 'Document.registerElement::' + callback;\n if (opts.prototype.hasOwnProperty(callback)) {\n var descriptor = Object.getOwnPropertyDescriptor(opts.prototype, callback);\n if (descriptor && descriptor.value) {\n descriptor.value = Zone.current.wrap(descriptor.value, source);\n _redefineProperty(opts.prototype, callback, descriptor);\n }\n else {\n opts.prototype[callback] = Zone.current.wrap(opts.prototype[callback], source);\n }\n }\n else if (opts.prototype[callback]) {\n opts.prototype[callback] = Zone.current.wrap(opts.prototype[callback], source);\n }\n });\n }\n return _registerElement.apply(document, [name, opts]);\n };\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar set = 'set';\nvar clear = 'clear';\nvar blockingMethods = ['alert', 'prompt', 'confirm'];\nvar _global = typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global;\npatchTimer(_global, set, clear, 'Timeout');\npatchTimer(_global, set, clear, 'Interval');\npatchTimer(_global, set, clear, 'Immediate');\npatchTimer(_global, 'request', 'cancel', 'AnimationFrame');\npatchTimer(_global, 'mozRequest', 'mozCancel', 'AnimationFrame');\npatchTimer(_global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');\nfor (var i = 0; i < blockingMethods.length; i++) {\n var name_1 = blockingMethods[i];\n patchMethod(_global, name_1, function (delegate, symbol, name) {\n return function (s, args) {\n return Zone.current.run(delegate, _global, args, name);\n };\n });\n}\neventTargetPatch(_global);\n// patch XMLHttpRequestEventTarget's addEventListener/removeEventListener\nvar XMLHttpRequestEventTarget = _global['XMLHttpRequestEventTarget'];\nif (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {\n patchEventTargetMethods(XMLHttpRequestEventTarget.prototype);\n}\npropertyDescriptorPatch(_global);\npatchClass('MutationObserver');\npatchClass('WebKitMutationObserver');\npatchClass('FileReader');\npropertyPatch();\nregisterElementPatch(_global);\n// Treat XMLHTTPRequest as a macrotask.\npatchXHR(_global);\nvar XHR_TASK = zoneSymbol('xhrTask');\nvar XHR_SYNC = zoneSymbol('xhrSync');\nvar XHR_LISTENER = zoneSymbol('xhrListener');\nvar XHR_SCHEDULED = zoneSymbol('xhrScheduled');\nfunction patchXHR(window) {\n function findPendingTask(target) {\n var pendingTask = target[XHR_TASK];\n return pendingTask;\n }\n function scheduleTask(task) {\n XMLHttpRequest[XHR_SCHEDULED] = false;\n var data = task.data;\n // remove existing event listener\n var listener = data.target[XHR_LISTENER];\n if (listener) {\n data.target.removeEventListener('readystatechange', listener);\n }\n var newListener = data.target[XHR_LISTENER] = function () {\n if (data.target.readyState === data.target.DONE) {\n // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with\n // readyState=4 multiple times, so we need to check task state here\n if (!data.aborted && XMLHttpRequest[XHR_SCHEDULED] && task.state === 'scheduled') {\n task.invoke();\n }\n }\n };\n data.target.addEventListener('readystatechange', newListener);\n var storedTask = data.target[XHR_TASK];\n if (!storedTask) {\n data.target[XHR_TASK] = task;\n }\n sendNative.apply(data.target, data.args);\n XMLHttpRequest[XHR_SCHEDULED] = true;\n return task;\n }\n function placeholderCallback() { }\n function clearTask(task) {\n var data = task.data;\n // Note - ideally, we would call data.target.removeEventListener here, but it's too late\n // to prevent it from firing. So instead, we store info for the event listener.\n data.aborted = true;\n return abortNative.apply(data.target, data.args);\n }\n var openNative = patchMethod(window.XMLHttpRequest.prototype, 'open', function () { return function (self, args) {\n self[XHR_SYNC] = args[2] == false;\n return openNative.apply(self, args);\n }; });\n var sendNative = patchMethod(window.XMLHttpRequest.prototype, 'send', function () { return function (self, args) {\n var zone = Zone.current;\n if (self[XHR_SYNC]) {\n // if the XHR is sync there is no task to schedule, just execute the code.\n return sendNative.apply(self, args);\n }\n else {\n var options = { target: self, isPeriodic: false, delay: null, args: args, aborted: false };\n return zone.scheduleMacroTask('XMLHttpRequest.send', placeholderCallback, options, scheduleTask, clearTask);\n }\n }; });\n var abortNative = patchMethod(window.XMLHttpRequest.prototype, 'abort', function (delegate) { return function (self, args) {\n var task = findPendingTask(self);\n if (task && typeof task.type == 'string') {\n // If the XHR has already completed, do nothing.\n // If the XHR has already been aborted, do nothing.\n // Fix #569, call abort multiple times before done will cause\n // macroTask task count be negative number\n if (task.cancelFn == null || (task.data && task.data.aborted)) {\n return;\n }\n task.zone.cancelTask(task);\n }\n // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no task\n // to cancel. Do nothing.\n }; });\n}\n/// GEO_LOCATION\nif (_global['navigator'] && _global['navigator'].geolocation) {\n patchPrototype(_global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);\n}\n// handle unhandled promise rejection\nfunction findPromiseRejectionHandler(evtName) {\n return function (e) {\n var eventTasks = findEventTask(_global, evtName);\n eventTasks.forEach(function (eventTask) {\n // windows has added unhandledrejection event listener\n // trigger the event listener\n var PromiseRejectionEvent = _global['PromiseRejectionEvent'];\n if (PromiseRejectionEvent) {\n var evt = new PromiseRejectionEvent(evtName, { promise: e.promise, reason: e.rejection });\n eventTask.invoke(evt);\n }\n });\n };\n}\nif (_global['PromiseRejectionEvent']) {\n Zone[zoneSymbol('unhandledPromiseRejectionHandler')] =\n findPromiseRejectionHandler('unhandledrejection');\n Zone[zoneSymbol('rejectionHandledHandler')] =\n findPromiseRejectionHandler('rejectionhandled');\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n})));\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/zone.js/dist/zone.js\n// module id = 175\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/styles.bundle.js.map b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/styles.bundle.js.map deleted file mode 100644 index 1b12d47fe8..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/styles.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./~/css-loader/lib/css-base.js","webpack:///./~/bootstrap/dist/css/bootstrap.min.css","webpack:///./src/styles.css","webpack:///./~/style-loader/addStyles.js","webpack:///./~/bootstrap/dist/css/bootstrap.min.css?fb7d","webpack:///./src/styles.css?c4d3"],"names":[],"mappings":";;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,gBAAgB,iBAAiB;AACjC;AACA;AACA,wCAAwC,gBAAgB;AACxD,IAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA,YAAY,oBAAoB;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACjDA;AACA;;;AAGA;AACA,6UAA8U,uBAAuB,iBAAiB,0BAA0B,8BAA8B,KAAK,SAAS,wCAAwC,cAAc,GAAG,cAAc,eAAe,uBAAuB,cAAc,OAAO,gBAAgB,GAAG,uBAAuB,SAAS,iBAAiB,IAAI,gCAAgC,cAAc,EAAE,6BAA6B,qCAAqC,iBAAiB,gBAAgB,YAAY,mBAAmB,0BAA0B,iCAAiC,SAAS,oBAAoB,SAAS,mBAAmB,cAAc,gCAAgC,cAAc,IAAI,kBAAkB,KAAK,sBAAsB,WAAW,MAAM,cAAc,QAAQ,cAAc,cAAc,kBAAkB,wBAAwB,IAAI,cAAc,IAAI,UAAU,YAAY,qBAAqB,sBAAsB,aAAa,SAAS,IAAI,kBAAkB,eAAe,gBAAgB,sCAAsC,uBAAuB,eAAe,iBAAiB,SAAS,aAAa,iBAAiB,cAAc,oBAAoB,qDAAqD,0BAA0B,wHAAwH,kBAAkB,UAAU,4GAA4G,8BAA8B,SAAS,wBAAwB,aAAa,2BAA2B,OAAO,sBAAsB,cAAc,cAAc,eAAe,UAAU,mBAAmB,SAAS,qBAAqB,wBAAwB,SAAS,cAAc,6BAA6B,sBAAsB,UAAU,kFAAkF,YAAY,cAAc,6BAA6B,oBAAoB,qFAAqF,wBAAwB,6BAA6B,0BAA0B,aAAa,aAAa,cAAc,QAAQ,kBAAkB,OAAO,qBAAqB,SAAS,aAAa,SAAS,aAAa,aAAa,mKAAmK,2BAA2B,0BAA0B,YAAY,0BAA0B,mBAAmB,iCAAiC,IAAI,+BAA+B,eAAe,sBAAsB,wBAAwB,MAAM,2BAA2B,OAAO,wBAAwB,QAAQ,UAAU,SAAS,MAAM,uBAAuB,QAAQ,aAAa,OAAO,sBAAsB,OAAO,mCAAmC,oBAAoB,gCAAgC,sCAAsC,iCAAiC,KAAK,sBAAsB,mBAAmB,mBAAmB,cAAc,mBAAmB,KAAK,6BAA6B,wCAAwC,KAAK,+GAA+G,eAAe,gBAAgB,gBAAgB,cAAc,sBAAsB,wBAAwB,oBAAoB,kBAAkB,aAAa,oBAAoB,EAAE,aAAa,mBAAmB,sCAAsC,YAAY,QAAQ,mBAAmB,kBAAkB,oBAAoB,SAAS,aAAa,mBAAmB,wBAAwB,gBAAgB,GAAG,gBAAgB,GAAG,oBAAoB,cAAc,WAAW,gBAAgB,EAAE,cAAc,qBAAqB,gBAAgB,cAAc,0BAA0B,8BAA8B,cAAc,qBAAqB,wEAAwE,cAAc,qBAAqB,oCAAoC,UAAU,IAAI,aAAa,mBAAmB,cAAc,OAAO,gBAAgB,IAAI,sBAAsB,cAAc,eAAe,gEAAgE,8BAA8B,0BAA0B,MAAM,yBAAyB,6BAA6B,QAAQ,mBAAmB,sBAAsB,cAAc,gBAAgB,oBAAoB,GAAG,gBAAgB,MAAM,qBAAqB,oBAAoB,aAAa,mBAAmB,0CAA0C,6BAA6B,oBAAoB,yDAAyD,mBAAmB,+EAA+E,2BAA2B,SAAS,gBAAgB,SAAS,YAAY,UAAU,SAAS,SAAS,OAAO,cAAc,WAAW,UAAU,oBAAoB,iBAAiB,oBAAoB,mBAAmB,wBAAwB,OAAO,qBAAqB,SAAS,uBAAuB,0CAA0C,oBAAoB,oBAAoB,gBAAgB,gBAAgB,cAAc,OAAO,iBAAiB,OAAO,eAAe,OAAO,kBAAkB,OAAO,iBAAiB,OAAO,kBAAkB,OAAO,eAAe,MAAM,kBAAkB,gBAAgB,WAAW,eAAe,gBAAgB,gBAAgB,WAAW,iBAAiB,gBAAgB,gBAAgB,WAAW,iBAAiB,gBAAgB,gBAAgB,WAAW,iBAAiB,gBAAgB,gBAAgB,GAAG,gBAAgB,mBAAmB,SAAS,oCAAoC,aAAa,cAAc,gBAAgB,WAAW,aAAa,yBAAyB,eAAe,eAAe,gBAAgB,aAAa,eAAe,gBAAgB,kBAAkB,qBAAqB,mCAAmC,iBAAiB,YAAY,cAAc,yBAAyB,YAAY,mBAAmB,mBAAmB,kBAAkB,iCAAiC,mBAAmB,cAAc,cAAc,cAAc,2BAA2B,0BAA0B,oBAAoB,mBAAmB,eAAe,iBAAiB,kCAAkC,cAAc,+CAA+C,aAAa,8CAA8C,0BAA0B,WAAW,eAAe,YAAY,eAAe,eAAe,sBAAsB,sBAAsB,qBAAqB,uCAAuC,+BAA+B,eAAe,YAAY,QAAQ,qBAAqB,YAAY,oBAAoB,cAAc,gBAAgB,cAAc,cAAc,kBAAkB,gFAAgF,KAAK,oBAAoB,cAAc,cAAc,yBAAyB,qBAAqB,OAAO,UAAU,cAAc,yBAAyB,IAAI,oBAAoB,cAAc,WAAW,yBAAyB,oBAAoB,QAAQ,UAAU,eAAe,gBAAgB,IAAI,cAAc,aAAa,mBAAmB,cAAc,cAAc,SAAS,UAAU,kBAAkB,cAAc,6BAA6B,gBAAgB,gBAAgB,iBAAiB,kBAAkB,WAAW,kBAAkB,iBAAiB,kBAAkB,mBAAmB,kBAAkB,yBAAyB,WAAW,mBAAmB,mBAAmB,yBAAyB,WAAW,mBAAmB,mBAAmB,yBAAyB,WAAW,mBAAmB,mBAAmB,0BAA0B,WAAW,mBAAmB,mBAAmB,yBAAyB,WAAW,YAAY,gBAAgB,yBAAyB,WAAW,YAAY,gBAAgB,yBAAyB,WAAW,YAAY,gBAAgB,0BAA0B,WAAW,aAAa,gBAAgB,iBAAiB,kBAAkB,iBAAiB,kBAAkB,mBAAmB,kBAAkB,yBAAyB,iBAAiB,mBAAmB,mBAAmB,yBAAyB,iBAAiB,mBAAmB,mBAAmB,yBAAyB,iBAAiB,mBAAmB,mBAAmB,0BAA0B,iBAAiB,mBAAmB,mBAAmB,KAAK,oBAAoB,oBAAoB,aAAa,mBAAmB,eAAe,mBAAmB,kBAAkB,yBAAyB,KAAK,mBAAmB,mBAAmB,yBAAyB,KAAK,mBAAmB,mBAAmB,yBAAyB,KAAK,mBAAmB,mBAAmB,0BAA0B,KAAK,mBAAmB,mBAAmB,YAAY,eAAe,cAAc,2CAA2C,gBAAgB,eAAe,wmBAAwmB,kBAAkB,WAAW,eAAe,mBAAmB,kBAAkB,yBAAyB,wmBAAwmB,mBAAmB,mBAAmB,yBAAyB,wmBAAwmB,mBAAmB,mBAAmB,yBAAyB,wmBAAwmB,mBAAmB,mBAAmB,0BAA0B,wmBAAwmB,mBAAmB,mBAAmB,KAAK,0BAA0B,aAAa,mBAAmB,oBAAoB,YAAY,eAAe,UAAU,mBAAmB,kBAAkB,cAAc,WAAW,OAAO,mBAAmB,uBAAuB,mBAAmB,oBAAoB,OAAO,mBAAmB,wBAAwB,oBAAoB,qBAAqB,OAAO,mBAAmB,iBAAiB,aAAa,cAAc,OAAO,mBAAmB,wBAAwB,oBAAoB,qBAAqB,OAAO,mBAAmB,wBAAwB,oBAAoB,qBAAqB,OAAO,mBAAmB,iBAAiB,aAAa,cAAc,OAAO,mBAAmB,wBAAwB,oBAAoB,qBAAqB,OAAO,mBAAmB,wBAAwB,oBAAoB,qBAAqB,OAAO,mBAAmB,iBAAiB,aAAa,cAAc,QAAQ,mBAAmB,wBAAwB,oBAAoB,qBAAqB,QAAQ,mBAAmB,wBAAwB,oBAAoB,qBAAqB,QAAQ,mBAAmB,kBAAkB,cAAc,eAAe,QAAQ,WAAW,QAAQ,gBAAgB,QAAQ,iBAAiB,QAAQ,UAAU,QAAQ,iBAAiB,QAAQ,iBAAiB,QAAQ,UAAU,QAAQ,iBAAiB,QAAQ,iBAAiB,QAAQ,UAAU,SAAS,iBAAiB,SAAS,iBAAiB,SAAS,WAAW,QAAQ,UAAU,QAAQ,eAAe,QAAQ,gBAAgB,QAAQ,SAAS,QAAQ,gBAAgB,QAAQ,gBAAgB,QAAQ,SAAS,QAAQ,gBAAgB,QAAQ,gBAAgB,QAAQ,SAAS,SAAS,gBAAgB,SAAS,gBAAgB,SAAS,UAAU,UAAU,sBAAsB,UAAU,uBAAuB,UAAU,gBAAgB,UAAU,uBAAuB,UAAU,uBAAuB,UAAU,gBAAgB,UAAU,uBAAuB,UAAU,uBAAuB,UAAU,gBAAgB,WAAW,uBAAuB,WAAW,uBAAuB,yBAAyB,QAAQ,0BAA0B,aAAa,mBAAmB,oBAAoB,YAAY,eAAe,aAAa,mBAAmB,kBAAkB,cAAc,WAAW,UAAU,mBAAmB,uBAAuB,mBAAmB,oBAAoB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,kBAAkB,cAAc,eAAe,WAAW,WAAW,WAAW,gBAAgB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,YAAY,iBAAiB,YAAY,iBAAiB,YAAY,WAAW,WAAW,UAAU,WAAW,eAAe,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,YAAY,gBAAgB,YAAY,gBAAgB,YAAY,UAAU,aAAa,cAAc,aAAa,sBAAsB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,cAAc,uBAAuB,cAAc,wBAAwB,yBAAyB,QAAQ,0BAA0B,aAAa,mBAAmB,oBAAoB,YAAY,eAAe,aAAa,mBAAmB,kBAAkB,cAAc,WAAW,UAAU,mBAAmB,uBAAuB,mBAAmB,oBAAoB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,kBAAkB,cAAc,eAAe,WAAW,WAAW,WAAW,gBAAgB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,YAAY,iBAAiB,YAAY,iBAAiB,YAAY,WAAW,WAAW,UAAU,WAAW,eAAe,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,YAAY,gBAAgB,YAAY,gBAAgB,YAAY,UAAU,aAAa,cAAc,aAAa,sBAAsB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,cAAc,uBAAuB,cAAc,wBAAwB,yBAAyB,QAAQ,0BAA0B,aAAa,mBAAmB,oBAAoB,YAAY,eAAe,aAAa,mBAAmB,kBAAkB,cAAc,WAAW,UAAU,mBAAmB,uBAAuB,mBAAmB,oBAAoB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,kBAAkB,cAAc,eAAe,WAAW,WAAW,WAAW,gBAAgB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,YAAY,iBAAiB,YAAY,iBAAiB,YAAY,WAAW,WAAW,UAAU,WAAW,eAAe,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,YAAY,gBAAgB,YAAY,gBAAgB,YAAY,UAAU,aAAa,cAAc,aAAa,sBAAsB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,cAAc,uBAAuB,cAAc,wBAAwB,0BAA0B,QAAQ,0BAA0B,aAAa,mBAAmB,oBAAoB,YAAY,eAAe,aAAa,mBAAmB,kBAAkB,cAAc,WAAW,UAAU,mBAAmB,uBAAuB,mBAAmB,oBAAoB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,wBAAwB,oBAAoB,qBAAqB,UAAU,mBAAmB,iBAAiB,aAAa,cAAc,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,wBAAwB,oBAAoB,qBAAqB,WAAW,mBAAmB,kBAAkB,cAAc,eAAe,WAAW,WAAW,WAAW,gBAAgB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,WAAW,iBAAiB,WAAW,iBAAiB,WAAW,UAAU,YAAY,iBAAiB,YAAY,iBAAiB,YAAY,WAAW,WAAW,UAAU,WAAW,eAAe,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,WAAW,gBAAgB,WAAW,gBAAgB,WAAW,SAAS,YAAY,gBAAgB,YAAY,gBAAgB,YAAY,UAAU,aAAa,cAAc,aAAa,sBAAsB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,aAAa,uBAAuB,aAAa,uBAAuB,aAAa,gBAAgB,cAAc,uBAAuB,cAAc,wBAAwB,OAAO,WAAW,eAAe,mBAAmB,oBAAoB,eAAe,mBAAmB,6BAA6B,gBAAgB,sBAAsB,gCAAgC,mBAAmB,6BAA6B,cAAc,sBAAsB,0BAA0B,cAAc,gBAAgB,yBAAyB,sCAAsC,yBAAyB,kDAAkD,wBAAwB,yCAAyC,iCAAiC,4BAA4B,kCAAkC,gDAAgD,kCAAkC,iCAAiC,kCAAkC,wEAAwE,kCAAkC,mDAAmD,yBAAyB,kCAAkC,yBAAyB,0EAA0E,yBAAyB,0CAA0C,yBAAyB,+BAA+B,yBAAyB,oEAAoE,yBAAyB,mDAAmD,yBAAyB,kCAAkC,yBAAyB,0EAA0E,yBAAyB,gDAAgD,yBAAyB,iCAAiC,yBAAyB,wEAAwE,yBAAyB,kBAAkB,WAAW,yBAAyB,kBAAkB,cAAc,yBAAyB,eAAe,WAAW,yBAAyB,4DAA4D,kBAAkB,8BAA8B,SAAS,kBAAkB,cAAc,WAAW,gBAAgB,4CAA4C,iCAAiC,SAAS,cAAc,cAAc,WAAW,qBAAqB,eAAe,iBAAiB,cAAc,sBAAsB,sBAAsB,4BAA4B,iCAAiC,qBAAqB,qFAAqF,6EAA6E,qEAAqE,0BAA0B,6BAA6B,SAAS,oBAAoB,cAAc,sBAAsB,qBAAqB,UAAU,yCAAyC,cAAc,UAAU,oCAAoC,cAAc,UAAU,2BAA2B,cAAc,UAAU,+CAA+C,yBAAyB,UAAU,uBAAuB,mBAAmB,gDAAgD,2BAA2B,qCAAqC,cAAc,sBAAsB,uCAAuC,cAAc,gBAAgB,kCAAkC,qCAAqC,gBAAgB,mBAAmB,mCAAmC,sCAAsC,kBAAkB,mBAAmB,mCAAmC,sCAAsC,kBAAkB,iBAAiB,kBAAkB,qBAAqB,gBAAgB,eAAe,qBAAqB,kBAAkB,qBAAqB,gBAAgB,iBAAiB,yBAAyB,mBAAmB,gZAAgZ,gBAAgB,eAAe,wHAAwH,qBAAqB,kBAAkB,oBAAoB,gQAAgQ,iBAAiB,wHAAwH,sBAAsB,kBAAkB,oBAAoB,gQAAgQ,mBAAmB,YAAY,mBAAmB,WAAW,cAAc,kBAAkB,YAAY,kBAAkB,cAAc,oBAAoB,uCAAuC,cAAc,mBAAmB,kBAAkB,qBAAqB,gBAAgB,eAAe,kBAAkB,kBAAkB,kBAAkB,qBAAqB,6BAA6B,gBAAgB,mBAAmB,qBAAqB,qCAAqC,sBAAsB,sCAAsC,mBAAmB,uBAAuB,kBAAkB,iEAAiE,sBAAsB,4BAA4B,0CAA0C,kCAAkC,8JAA8J,cAAc,2BAA2B,qBAAqB,gCAAgC,cAAc,qBAAqB,yBAAyB,mCAAmC,0CAA0C,iOAAiO,8JAA8J,cAAc,2BAA2B,qBAAqB,gCAAgC,cAAc,qBAAqB,sBAAsB,mCAAmC,0CAA0C,0SAA0S,yJAAyJ,cAAc,0BAA0B,qBAAqB,+BAA+B,cAAc,qBAAqB,yBAAyB,iCAAiC,0CAA0C,2QAA2Q,aAAa,oBAAoB,oBAAoB,aAAa,uBAAuB,8BAA8B,6BAA6B,mBAAmB,yBAAyB,sBAAsB,mBAAmB,yBAAyB,WAAW,yBAAyB,mBAAmB,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,wBAAwB,qBAAqB,uBAAuB,gBAAgB,yBAAyB,oBAAoB,oBAAoB,aAAa,mBAAmB,kBAAkB,cAAc,uBAAuB,8BAA8B,6BAA6B,mBAAmB,yBAAyB,sBAAsB,mBAAmB,gBAAgB,2BAA2B,qBAAqB,WAAW,sBAAsB,kCAAkC,qBAAqB,0BAA0B,WAAW,iCAAiC,gBAAgB,sBAAsB,yBAAyB,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,wBAAwB,qBAAqB,uBAAuB,WAAW,aAAa,gBAAgB,+BAA+B,eAAe,+BAA+B,kBAAkB,aAAa,oBAAoB,cAAc,6BAA6B,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,wBAAwB,qBAAqB,uBAAuB,eAAe,uCAAuC,gBAAgB,qBAAqB,oBAAoB,2BAA2B,kDAAkD,OAAO,KAAK,qBAAqB,gBAAgB,iBAAiB,kBAAkB,mBAAmB,sBAAsB,yBAAyB,sBAAsB,qBAAqB,iBAAiB,6BAA6B,mBAAmB,eAAe,qBAAqB,uCAAuC,+BAA+B,sBAAsB,qBAAqB,sBAAsB,UAAU,yCAAyC,4BAA4B,mBAAmB,YAAY,wBAAwB,sBAAsB,wCAAwC,oBAAoB,aAAa,WAAW,yBAAyB,qBAAqB,mBAAmB,WAAW,yBAAyB,qBAAqB,sCAAsC,wCAAwC,4CAA4C,yBAAyB,qBAAqB,2EAA2E,WAAW,yBAAyB,sBAAsB,qBAAqB,eAAe,cAAc,sBAAsB,kBAAkB,qBAAqB,cAAc,yBAAyB,qBAAqB,0CAA0C,0CAA0C,gDAAgD,sBAAsB,kBAAkB,iFAAiF,cAAc,yBAAyB,sBAAsB,qBAAqB,UAAU,WAAW,yBAAyB,qBAAqB,gBAAgB,WAAW,yBAAyB,qBAAqB,gCAAgC,yCAAyC,sCAAsC,yBAAyB,qBAAqB,kEAAkE,WAAW,yBAAyB,sBAAsB,qBAAqB,aAAa,WAAW,yBAAyB,qBAAqB,mBAAmB,WAAW,yBAAyB,qBAAqB,sCAAsC,wCAAwC,4CAA4C,yBAAyB,qBAAqB,2EAA2E,WAAW,yBAAyB,sBAAsB,qBAAqB,aAAa,WAAW,yBAAyB,qBAAqB,mBAAmB,WAAW,yBAAyB,qBAAqB,sCAAsC,yCAAyC,4CAA4C,yBAAyB,qBAAqB,2EAA2E,WAAW,yBAAyB,sBAAsB,qBAAqB,YAAY,WAAW,yBAAyB,qBAAqB,kBAAkB,WAAW,yBAAyB,qBAAqB,oCAAoC,wCAAwC,0CAA0C,yBAAyB,qBAAqB,wEAAwE,WAAW,yBAAyB,sBAAsB,qBAAqB,qBAAqB,cAAc,sBAAsB,6BAA6B,qBAAqB,2BAA2B,WAAW,yBAAyB,qBAAqB,sDAAsD,wCAAwC,4DAA4D,cAAc,6BAA6B,mGAAmG,WAAW,yBAAyB,qBAAqB,uBAAuB,WAAW,sBAAsB,6BAA6B,kBAAkB,6BAA6B,WAAW,sBAAsB,kBAAkB,0DAA0D,0CAA0C,gEAAgE,WAAW,6BAA6B,yGAAyG,WAAW,sBAAsB,kBAAkB,kBAAkB,cAAc,sBAAsB,6BAA6B,qBAAqB,wBAAwB,WAAW,yBAAyB,qBAAqB,gDAAgD,yCAAyC,sDAAsD,cAAc,6BAA6B,0FAA0F,WAAW,yBAAyB,qBAAqB,qBAAqB,cAAc,sBAAsB,6BAA6B,qBAAqB,2BAA2B,WAAW,yBAAyB,qBAAqB,sDAAsD,wCAAwC,4DAA4D,cAAc,6BAA6B,mGAAmG,WAAW,yBAAyB,qBAAqB,qBAAqB,cAAc,sBAAsB,6BAA6B,qBAAqB,2BAA2B,WAAW,yBAAyB,qBAAqB,sDAAsD,yCAAyC,4DAA4D,cAAc,6BAA6B,mGAAmG,WAAW,yBAAyB,qBAAqB,oBAAoB,cAAc,sBAAsB,6BAA6B,qBAAqB,0BAA0B,WAAW,yBAAyB,qBAAqB,oDAAoD,wCAAwC,0DAA0D,cAAc,6BAA6B,gGAAgG,WAAW,yBAAyB,qBAAqB,UAAU,gBAAgB,cAAc,gBAAgB,+DAA+D,6BAA6B,2CAA2C,yBAAyB,gBAAgB,yBAAyB,gCAAgC,cAAc,0BAA0B,6BAA6B,mBAAmB,cAAc,kDAAkD,qBAAqB,2BAA2B,sBAAsB,kBAAkB,oBAAoB,2BAA2B,qBAAqB,kBAAkB,oBAAoB,WAAW,cAAc,WAAW,sBAAsB,iBAAiB,sFAAsF,WAAW,MAAM,UAAU,uCAAuC,+BAA+B,WAAW,UAAU,UAAU,aAAa,eAAe,cAAc,iBAAiB,kBAAkB,oBAAoB,wBAAwB,YAAY,kBAAkB,SAAS,gBAAgB,oCAAoC,4BAA4B,kBAAkB,kBAAkB,wBAAwB,qBAAqB,QAAQ,SAAS,iBAAiB,sBAAsB,aAAa,sBAAsB,oCAAoC,mCAAmC,uBAAuB,UAAU,gCAAgC,aAAa,yBAAyB,eAAe,kBAAkB,SAAS,OAAO,aAAa,aAAa,WAAW,gBAAgB,gBAAgB,mBAAmB,eAAe,cAAc,gBAAgB,gBAAgB,sBAAsB,4BAA4B,iCAAiC,qBAAqB,kBAAkB,WAAW,eAAe,gBAAgB,yBAAyB,eAAe,cAAc,WAAW,mBAAmB,WAAW,gBAAgB,cAAc,mBAAmB,mBAAmB,eAAe,SAAS,0CAA0C,cAAc,qBAAqB,yBAAyB,4CAA4C,WAAW,qBAAqB,yBAAyB,gDAAgD,cAAc,mBAAmB,6BAA6B,qBAAqB,cAAc,QAAQ,UAAU,qBAAqB,QAAQ,UAAU,oBAAoB,WAAW,OAAO,iBAAiB,cAAc,qBAAqB,gBAAgB,kBAAkB,cAAc,mBAAmB,mBAAmB,eAAe,MAAM,QAAQ,SAAS,OAAO,YAAY,uBAAuB,SAAS,YAAY,sBAAsB,+BAA+B,kBAAkB,2BAA2B,2BAA2B,oBAAoB,sBAAsB,yCAAyC,kBAAkB,mBAAmB,kBAAkB,cAAc,qDAAqD,UAAU,mKAAmK,UAAU,4PAA4P,iBAAiB,aAAa,oBAAoB,oBAAoB,aAAa,uBAAuB,oBAAoB,2BAA2B,0BAA0B,WAAW,yEAAyE,gBAAgB,4BAA4B,cAAc,mEAAmE,6BAA6B,0BAA0B,2FAA2F,4BAA4B,yBAAyB,sBAAsB,WAAW,8DAA8D,gBAAgB,uIAAuI,6BAA6B,0BAA0B,oEAAoE,4BAA4B,yBAAyB,oEAAoE,UAAU,4BAA4B,qBAAqB,oBAAoB,mCAAmC,cAAc,yEAAyE,sBAAsB,qBAAqB,yEAAyE,uBAAuB,sBAAsB,oBAAoB,2BAA2B,2BAA2B,oBAAoB,4BAA4B,6BAA6B,0BAA0B,sBAAsB,wBAAwB,qBAAqB,uBAAuB,wBAAwB,qBAAqB,uBAAuB,wDAAwD,WAAW,gJAAgJ,gBAAgB,cAAc,4DAA4D,gBAAgB,sDAAsD,6BAA6B,4BAA4B,sDAAsD,0BAA0B,yBAAyB,uEAAuE,gBAAgB,yJAAyJ,6BAA6B,4BAA4B,6EAA6E,0BAA0B,yBAAyB,gNAAgN,kBAAkB,mBAAmB,oBAAoB,aAAa,kBAAkB,oBAAoB,oBAAoB,aAAa,WAAW,2BAA2B,kBAAkB,UAAU,mBAAmB,kBAAkB,cAAc,SAAS,gBAAgB,oGAAoG,UAAU,+DAA+D,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,wBAAwB,qBAAqB,uBAAuB,wKAAwK,gBAAgB,oCAAoC,mBAAmB,sBAAsB,mBAAmB,qBAAqB,gBAAgB,eAAe,gBAAgB,iBAAiB,cAAc,kBAAkB,yBAAyB,iCAAiC,qBAAqB,8HAA8H,qBAAqB,kBAAkB,oBAAoB,8HAA8H,sBAAsB,kBAAkB,oBAAoB,6EAA6E,aAAa,+WAA+W,6BAA6B,0BAA0B,oCAAoC,eAAe,8VAA8V,4BAA4B,yBAAyB,mDAAmD,cAAc,iBAAiB,kBAAkB,YAAY,mBAAmB,sBAAsB,kBAAkB,mBAAmB,gBAAgB,YAAY,2BAA2B,iBAAiB,qFAAqF,UAAU,oFAAoF,kBAAkB,sFAAsF,UAAU,iBAAiB,wSAAwS,UAAU,gBAAgB,kBAAkB,2BAA2B,2BAA2B,oBAAoB,kBAAkB,oBAAoB,kBAAkB,eAAe,sBAAsB,kBAAkB,WAAW,UAAU,wDAAwD,WAAW,yBAAyB,sDAAsD,4CAA4C,uDAAuD,WAAW,yBAAyB,yDAAyD,mBAAmB,yBAAyB,2DAA2D,cAAc,mBAAmB,0BAA0B,kBAAkB,WAAW,OAAO,cAAc,WAAW,YAAY,oBAAoB,yBAAyB,sBAAsB,qBAAqB,iBAAiB,sBAAsB,4BAA4B,kCAAkC,wBAAwB,2CAA2C,qBAAqB,yEAAyE,0CAA0C,kLAAkL,+EAA+E,yBAAyB,0CAA0C,+HAA+H,wCAAwC,kBAAkB,sEAAsE,0CAA0C,4HAA4H,yBAAyB,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,yCAAyC,qBAAqB,yDAAyD,cAAc,eAAe,qBAAqB,eAAe,2BAA2B,uCAAuC,iBAAiB,cAAc,sBAAsB,yCAAyC,2KAA2K,yBAAyB,iCAAiC,qBAAqB,qBAAqB,wBAAwB,qBAAqB,qBAAqB,UAAU,gCAAgC,cAAc,sBAAsB,wBAAwB,cAAc,mBAAmB,yBAAyB,2BAA2B,UAAU,kBAAkB,oBAAoB,uBAAuB,cAAc,aAAa,kBAAkB,qBAAqB,eAAe,cAAc,gBAAgB,eAAe,mBAAmB,gBAAgB,eAAe,cAAc,SAAS,wBAAwB,UAAU,qBAAqB,kBAAkB,MAAM,QAAQ,OAAO,UAAU,cAAc,mBAAmB,gBAAgB,cAAc,oBAAoB,yBAAyB,sBAAsB,qBAAqB,iBAAiB,sBAAsB,iCAAiC,qBAAqB,qCAAqC,2BAA2B,6BAA6B,kBAAkB,SAAS,WAAW,YAAY,UAAU,cAAc,cAAc,mBAAmB,gBAAgB,cAAc,yBAAyB,iCAAiC,gCAAgC,sCAAsC,mBAAmB,KAAK,oBAAoB,oBAAoB,aAAa,eAAe,gBAAgB,gBAAgB,UAAU,cAAc,iBAAiB,gCAAgC,qBAAqB,mBAAmB,cAAc,mBAAmB,UAAU,6BAA6B,oBAAoB,mBAAmB,oBAAoB,6BAA6B,+BAA+B,8BAA8B,oDAAoD,kCAAkC,6BAA6B,cAAc,6BAA6B,yBAAyB,8DAA8D,cAAc,sBAAsB,4BAA4B,yBAAyB,gBAAgB,0BAA0B,yBAAyB,qBAAqB,qBAAqB,gEAAgE,WAAW,eAAe,yBAAyB,oBAAoB,mBAAmB,kBAAkB,cAAc,kBAAkB,yBAAyB,mBAAmB,kBAAkB,cAAc,kBAAkB,uBAAuB,aAAa,qBAAqB,cAAc,QAAQ,kBAAkB,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,mBAAmB,cAAc,qBAAqB,mBAAmB,sBAAsB,kBAAkB,kBAAkB,oBAAoB,mBAAmB,wCAAwC,qBAAqB,YAAY,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,eAAe,gBAAgB,gBAAgB,sBAAsB,gBAAgB,eAAe,aAAa,qBAAqB,oBAAoB,uBAAuB,gBAAgB,8BAA8B,0BAA0B,sBAAsB,sBAAsB,kBAAkB,cAAc,eAAe,6BAA6B,qBAAqB,4CAA4C,qBAAqB,qBAAqB,qBAAqB,YAAY,aAAa,sBAAsB,aAAa,mCAAmC,0BAA0B,qBAAqB,kBAAkB,UAAU,sBAAsB,kBAAkB,WAAW,yBAAyB,8CAA8C,gBAAgB,WAAW,8BAA8B,gBAAgB,gBAAgB,yBAAyB,mBAAmB,8BAA8B,6BAA6B,uBAAuB,mBAAmB,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,+BAA+B,8BAA8B,6BAA6B,uBAAuB,mBAAmB,yCAAyC,oBAAoB,mBAAmB,8BAA8B,oBAAoB,oBAAoB,aAAa,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,oCAAoC,8BAA8B,8BAA8B,uBAAuB,WAAW,mCAAmC,cAAc,yBAAyB,iDAAiD,gBAAgB,WAAW,iCAAiC,gBAAgB,gBAAgB,yBAAyB,sBAAsB,8BAA8B,6BAA6B,uBAAuB,mBAAmB,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,kCAAkC,8BAA8B,6BAA6B,uBAAuB,mBAAmB,4CAA4C,oBAAoB,mBAAmB,iCAAiC,oBAAoB,oBAAoB,aAAa,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,uCAAuC,8BAA8B,8BAA8B,uBAAuB,WAAW,sCAAsC,cAAc,yBAAyB,iDAAiD,gBAAgB,WAAW,iCAAiC,gBAAgB,gBAAgB,yBAAyB,sBAAsB,8BAA8B,6BAA6B,uBAAuB,mBAAmB,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,kCAAkC,8BAA8B,6BAA6B,uBAAuB,mBAAmB,4CAA4C,oBAAoB,mBAAmB,iCAAiC,oBAAoB,oBAAoB,aAAa,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,uCAAuC,8BAA8B,8BAA8B,uBAAuB,WAAW,sCAAsC,cAAc,0BAA0B,iDAAiD,gBAAgB,WAAW,iCAAiC,gBAAgB,gBAAgB,0BAA0B,sBAAsB,8BAA8B,6BAA6B,uBAAuB,mBAAmB,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,kCAAkC,8BAA8B,6BAA6B,uBAAuB,mBAAmB,4CAA4C,oBAAoB,mBAAmB,iCAAiC,oBAAoB,oBAAoB,aAAa,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,uCAAuC,8BAA8B,8BAA8B,uBAAuB,WAAW,sCAAsC,cAAc,sBAAsB,8BAA8B,6BAA6B,uBAAuB,mBAAmB,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,iDAAiD,gBAAgB,WAAW,iCAAiC,gBAAgB,eAAe,kCAAkC,8BAA8B,6BAA6B,uBAAuB,mBAAmB,4CAA4C,oBAAoB,mBAAmB,iCAAiC,oBAAoB,oBAAoB,aAAa,qBAAqB,iBAAiB,yBAAyB,sBAAsB,mBAAmB,uCAAuC,8BAA8B,8BAA8B,uBAAuB,WAAW,sCAAsC,aAAa,0DAA0D,qBAAqB,4IAA4I,qBAAqB,oCAAoC,qBAAqB,oFAAoF,qBAAqB,6CAA6C,qBAAqB,0KAA0K,qBAAqB,8BAA8B,4BAA4B,mCAAmC,0CAA0C,6NAA6N,2BAA2B,qBAAqB,8DAA8D,WAAW,oJAAoJ,WAAW,sCAAsC,2BAA2B,wFAAwF,4BAA4B,+CAA+C,4BAA4B,kLAAkL,WAAW,gCAAgC,kCAAkC,qCAAqC,0CAA0C,mOAAmO,6BAA6B,2BAA2B,MAAM,kBAAkB,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,sBAAsB,kCAAkC,qBAAqB,YAAY,mBAAmB,kBAAkB,cAAc,gBAAgB,YAAY,qBAAqB,eAAe,oBAAoB,gBAAgB,sBAAsB,gBAAgB,iBAAiB,qBAAqB,sBAAsB,oBAAoB,2DAA2D,+BAA+B,8BAA8B,yDAAyD,kCAAkC,iCAAiC,aAAa,uBAAuB,gBAAgB,yBAAyB,yCAAyC,yBAAyB,wDAAwD,aAAa,uBAAuB,yBAAyB,sCAAsC,wBAAwB,wDAAwD,kBAAkB,sBAAsB,sBAAsB,qBAAqB,gBAAgB,mBAAmB,sBAAsB,qBAAqB,cAAc,yBAAyB,qBAAqB,sDAAsD,6BAA6B,cAAc,yBAAyB,qBAAqB,sDAAsD,6BAA6B,WAAW,yBAAyB,qBAAqB,gDAAgD,6BAA6B,cAAc,yBAAyB,qBAAqB,sDAAsD,6BAA6B,aAAa,yBAAyB,qBAAqB,oDAAoD,6BAA6B,sBAAsB,6BAA6B,qBAAqB,wBAAwB,6BAA6B,kBAAkB,mBAAmB,6BAA6B,qBAAqB,sBAAsB,6BAA6B,qBAAqB,sBAAsB,6BAA6B,qBAAqB,qBAAqB,6BAA6B,qBAAqB,cAAc,4BAA4B,sDAAsD,6BAA6B,kCAAkC,+GAA+G,WAAW,iIAAiI,4BAA4B,8DAA8D,WAAW,iBAAiB,UAAU,gBAAgB,cAAc,UAAU,iCAAiC,kBAAkB,kBAAkB,MAAM,QAAQ,SAAS,OAAO,gBAAgB,cAAc,2CAA2C,0CAA0C,iBAAiB,8CAA8C,6CAA6C,yBAAyB,WAAW,oBAAoB,oBAAoB,aAAa,uBAAuB,8BAA8B,6BAA6B,mBAAmB,iBAAiB,oBAAoB,oBAAoB,aAAa,mBAAmB,gBAAgB,YAAY,4BAA4B,6BAA6B,0BAA0B,sBAAsB,mCAAmC,iBAAiB,kCAAkC,mBAAmB,yBAAyB,YAAY,oBAAoB,oBAAoB,aAAa,uBAAuB,8BAA8B,6BAA6B,mBAAmB,kBAAkB,mBAAmB,gBAAgB,YAAY,wBAAwB,cAAc,cAAc,8BAA8B,6BAA6B,0BAA0B,4CAA4C,0BAA0B,+CAA+C,6BAA6B,6BAA6B,4BAA4B,yBAAyB,2CAA2C,yBAAyB,8CAA8C,4BAA4B,qDAAqD,gBAAgB,yIAAyI,iBAAiB,yBAAyB,cAAc,uBAAuB,oBAAoB,eAAe,2BAA2B,wBAAwB,mBAAmB,oBAAoB,qBAAqB,WAAW,sBAAsB,YAAY,oBAAoB,mBAAmB,gBAAgB,yBAAyB,qBAAqB,mBAAmB,cAAc,aAAa,WAAW,iBAAiB,WAAW,0CAA0C,qBAAqB,oBAAoB,mBAAmB,cAAc,cAAc,gDAAgD,0BAA0B,gDAAgD,qBAAqB,wBAAwB,cAAc,YAAY,oBAAoB,oBAAoB,aAAa,eAAe,gBAAgB,qBAAqB,kCAAkC,cAAc,iCAAiC,8BAA8B,iCAAiC,kCAAkC,+BAA+B,6BAA6B,UAAU,WAAW,yBAAyB,qBAAqB,+BAA+B,cAAc,oBAAoB,mBAAmB,sBAAsB,kBAAkB,WAAW,kBAAkB,cAAc,qBAAqB,iBAAiB,iBAAiB,cAAc,sBAAsB,sBAAsB,kCAAkC,cAAc,qBAAqB,yBAAyB,kBAAkB,0BAA0B,sBAAsB,kBAAkB,iDAAiD,gCAAgC,6BAA6B,gDAAgD,iCAAiC,8BAA8B,0BAA0B,qBAAqB,kBAAkB,iDAAiD,gCAAgC,6BAA6B,gDAAgD,iCAAiC,8BAA8B,OAAO,qBAAqB,mBAAmB,cAAc,gBAAgB,cAAc,WAAW,kBAAkB,mBAAmB,wBAAwB,qBAAqB,aAAa,aAAa,YAAY,kBAAkB,SAAS,4BAA4B,WAAW,qBAAqB,eAAe,YAAY,mBAAmB,kBAAkB,oBAAoB,eAAe,yBAAyB,sDAAsD,yBAAyB,eAAe,yBAAyB,sDAAsD,yBAAyB,eAAe,yBAAyB,sDAAsD,yBAAyB,YAAY,yBAAyB,gDAAgD,yBAAyB,eAAe,yBAAyB,sDAAsD,yBAAyB,cAAc,yBAAyB,oDAAoD,yBAAyB,WAAW,kBAAkB,mBAAmB,yBAAyB,oBAAoB,yBAAyB,WAAW,mBAAmB,cAAc,yBAAyB,iBAAiB,gBAAgB,eAAe,gBAAgB,OAAO,uBAAuB,mBAAmB,6BAA6B,qBAAqB,eAAe,cAAc,YAAY,gBAAgB,0BAA0B,kBAAkB,YAAY,eAAe,uBAAuB,cAAc,eAAe,yBAAyB,qBAAqB,cAAc,kBAAkB,yBAAyB,2BAA2B,cAAc,YAAY,yBAAyB,qBAAqB,cAAc,eAAe,yBAAyB,wBAAwB,cAAc,eAAe,yBAAyB,qBAAqB,cAAc,kBAAkB,yBAAyB,2BAA2B,cAAc,cAAc,yBAAyB,qBAAqB,cAAc,iBAAiB,yBAAyB,0BAA0B,cAAc,wCAAwC,KAAK,2BAA2B,GAAG,yBAAyB,gCAAgC,KAAK,2BAA2B,GAAG,yBAAyB,UAAU,oBAAoB,oBAAoB,aAAa,gBAAgB,iBAAiB,iBAAiB,kBAAkB,yBAAyB,qBAAqB,cAAc,YAAY,WAAW,yBAAyB,sBAAsB,0LAA0L,kLAAkL,0BAA0B,uBAAuB,0DAA0D,kDAAkD,OAAO,oBAAoB,oBAAoB,aAAa,wBAAwB,qBAAqB,uBAAuB,YAAY,mBAAmB,gBAAgB,YAAY,YAAY,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,eAAe,gBAAgB,wBAAwB,WAAW,cAAc,mBAAmB,iDAAiD,cAAc,4DAA4D,cAAc,qBAAqB,yBAAyB,+BAA+B,cAAc,yBAAyB,iBAAiB,kBAAkB,oBAAoB,oBAAoB,aAAa,uBAAuB,8BAA8B,6BAA6B,mBAAmB,yBAAyB,sBAAsB,mBAAmB,uBAAuB,mBAAmB,sBAAsB,kCAAkC,6BAA6B,+BAA+B,8BAA8B,4BAA4B,gBAAgB,kCAAkC,iCAAiC,8CAA8C,qBAAqB,oDAAoD,cAAc,mBAAmB,sBAAsB,sGAAsG,cAAc,gGAAgG,cAAc,wBAAwB,UAAU,WAAW,yBAAyB,qBAAqB,gKAAgK,cAAc,8CAA8C,cAAc,mCAAmC,eAAe,cAAc,gBAAgB,2DAA2D,aAAa,yDAAyD,gBAAgB,yBAAyB,cAAc,yBAAyB,yDAAyD,cAAc,2GAA2G,cAAc,0IAA0I,cAAc,yBAAyB,uEAAuE,WAAW,yBAAyB,qBAAqB,sBAAsB,cAAc,yBAAyB,mDAAmD,cAAc,qGAAqG,cAAc,8HAA8H,cAAc,yBAAyB,iEAAiE,WAAW,yBAAyB,qBAAqB,yBAAyB,cAAc,yBAAyB,yDAAyD,cAAc,2GAA2G,cAAc,0IAA0I,cAAc,yBAAyB,uEAAuE,WAAW,yBAAyB,qBAAqB,wBAAwB,cAAc,yBAAyB,uDAAuD,cAAc,yGAAyG,cAAc,sIAAsI,cAAc,yBAAyB,qEAAqE,WAAW,yBAAyB,qBAAqB,kBAAkB,kBAAkB,cAAc,WAAW,UAAU,gBAAgB,0BAA0B,cAAc,aAAa,2IAA2I,kBAAkB,MAAM,SAAS,OAAO,WAAW,YAAY,SAAS,gCAAgC,uBAAuB,gCAAgC,mBAAmB,+BAA+B,gBAAgB,+BAA+B,iBAAiB,OAAO,YAAY,iBAAiB,gBAAgB,cAAc,WAAW,yBAAyB,WAAW,0BAA0B,WAAW,qBAAqB,eAAe,YAAY,aAAa,UAAU,eAAe,eAAe,SAAS,wBAAwB,YAAY,gBAAgB,OAAO,eAAe,MAAM,QAAQ,SAAS,OAAO,aAAa,aAAa,gBAAgB,UAAU,0BAA0B,kDAAkD,0CAA0C,kCAAkC,kEAAkE,iEAAiE,oCAAoC,4BAA4B,0BAA0B,iCAAiC,yBAAyB,mBAAmB,kBAAkB,gBAAgB,cAAc,kBAAkB,WAAW,YAAY,eAAe,kBAAkB,oBAAoB,oBAAoB,aAAa,4BAA4B,6BAA6B,0BAA0B,sBAAsB,sBAAsB,4BAA4B,gCAAgC,oBAAoB,UAAU,gBAAgB,eAAe,MAAM,QAAQ,SAAS,OAAO,aAAa,sBAAsB,qBAAqB,UAAU,qBAAqB,WAAW,cAAc,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,yBAAyB,sBAAsB,8BAA8B,aAAa,gCAAgC,aAAa,gBAAgB,gBAAgB,YAAY,kBAAkB,mBAAmB,kBAAkB,cAAc,aAAa,cAAc,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,qBAAqB,kBAAkB,yBAAyB,aAAa,6BAA6B,iCAAiC,mBAAmB,gCAAgC,oBAAoB,yBAAyB,kBAAkB,YAAY,WAAW,YAAY,gBAAgB,yBAAyB,cAAc,gBAAgB,iBAAiB,UAAU,iBAAiB,yBAAyB,UAAU,iBAAiB,SAAS,kBAAkB,aAAa,cAAc,+GAA+G,kBAAkB,gBAAgB,sBAAsB,gBAAgB,gBAAgB,gBAAgB,iBAAiB,qBAAqB,iBAAiB,oBAAoB,mBAAmB,kBAAkB,oBAAoB,kBAAkB,qBAAqB,UAAU,cAAc,WAAW,gEAAgE,cAAc,gBAAgB,8GAA8G,SAAS,SAAS,iBAAiB,aAAa,uBAAuB,sBAAsB,gEAAgE,cAAc,gBAAgB,8GAA8G,QAAQ,OAAO,gBAAgB,aAAa,2BAA2B,wBAAwB,gEAAgE,cAAc,eAAe,8GAA8G,MAAM,SAAS,iBAAiB,aAAa,uBAAuB,yBAAyB,gEAAgE,cAAc,iBAAiB,8GAA8G,QAAQ,QAAQ,gBAAgB,aAAa,2BAA2B,uBAAuB,eAAe,gBAAgB,gBAAgB,WAAW,kBAAkB,sBAAsB,qBAAqB,uBAAuB,kBAAkB,QAAQ,SAAS,yBAAyB,mBAAmB,SAAS,kBAAkB,MAAM,OAAO,aAAa,cAAc,gBAAgB,YAAY,+GAA+G,kBAAkB,gBAAgB,sBAAsB,gBAAgB,gBAAgB,gBAAgB,iBAAiB,qBAAqB,iBAAiB,oBAAoB,mBAAmB,kBAAkB,oBAAoB,kBAAkB,qBAAqB,sBAAsB,4BAA4B,gCAAgC,oBAAoB,gEAAgE,iBAAiB,8JAA8J,SAAS,sBAAsB,gFAAgF,aAAa,kBAAkB,iCAAiC,8EAA8E,aAAa,kBAAkB,sBAAsB,gEAAgE,iBAAiB,8JAA8J,QAAQ,oBAAoB,gFAAgF,WAAW,iBAAiB,mCAAmC,8EAA8E,WAAW,iBAAiB,wBAAwB,gEAAgE,gBAAgB,8JAA8J,SAAS,mBAAmB,gFAAgF,UAAU,kBAAkB,oCAAoC,8EAA8E,UAAU,kBAAkB,4BAA4B,8GAA8G,kBAAkB,MAAM,SAAS,cAAc,WAAW,kBAAkB,aAAa,gCAAgC,gEAAgE,kBAAkB,8JAA8J,QAAQ,qBAAqB,gFAAgF,YAAY,iBAAiB,kCAAkC,8EAA8E,YAAY,iBAAiB,uBAAuB,eAAe,iBAAiB,gBAAgB,eAAe,yBAAyB,gCAAgC,0CAA0C,yCAAyC,qBAAqB,aAAa,iBAAiB,iBAAiB,iCAAiC,kBAAkB,cAAc,QAAQ,SAAS,yBAAyB,mBAAmB,iBAAiB,aAAa,kBAAkB,gBAAgB,aAAa,kBAAkB,UAAU,kBAAkB,gBAAgB,kBAAkB,WAAW,gBAAgB,eAAe,kBAAkB,aAAa,WAAW,8BAA8B,eAAe,qDAAqD,6CAA6C,qCAAqC,wEAAwE,uEAAuE,mCAAmC,2BAA2B,2BAA2B,oBAAoB,uFAAuF,eAAe,qDAAqD,6CAA6C,qCAAqC,wEAAwE,uEAAuE,mCAAmC,2BAA2B,2BAA2B,oBAAoB,8DAA8D,oBAAoB,oBAAoB,aAAa,wCAAwC,kBAAkB,MAAM,8BAA8B,+EAA+E,qCAAqC,6BAA6B,gDAAgD,wCAAwC,gCAAgC,+CAA+C,yCAAyC,kCAAkC,uFAAuF,+EAA+E,qCAAqC,6BAA6B,gDAAgD,wCAAwC,gCAAgC,+CAA+C,yCAAyC,kCAAkC,8CAA8C,kBAAkB,MAAM,SAAS,oBAAoB,oBAAoB,aAAa,yBAAyB,sBAAsB,mBAAmB,wBAAwB,qBAAqB,uBAAuB,UAAU,WAAW,kBAAkB,WAAW,oHAAoH,WAAW,qBAAqB,UAAU,WAAW,uBAAuB,OAAO,uBAAuB,QAAQ,wDAAwD,qBAAqB,WAAW,YAAY,+CAA+C,0BAA0B,4BAA4B,0CAA0C,qKAAqK,4BAA4B,0CAA0C,uKAAuK,qBAAqB,kBAAkB,QAAQ,YAAY,OAAO,WAAW,oBAAoB,oBAAoB,aAAa,wBAAwB,qBAAqB,uBAAuB,eAAe,iBAAiB,gBAAgB,gBAAgB,wBAAwB,kBAAkB,mBAAmB,kBAAkB,cAAc,eAAe,WAAW,iBAAiB,gBAAgB,mBAAmB,eAAe,sCAAsC,gCAAgC,kBAAkB,UAAU,OAAO,qBAAqB,WAAW,YAAY,aAAa,+BAA+B,kBAAkB,aAAa,OAAO,qBAAqB,WAAW,YAAY,aAAa,6BAA6B,sBAAsB,kBAAkB,kBAAkB,UAAU,YAAY,SAAS,WAAW,iBAAiB,oBAAoB,WAAW,kBAAkB,gBAAgB,kCAAkC,WAAW,6BAA6B,cAAc,gCAAgC,cAAc,gCAAgC,mBAAmB,qCAAqC,gBAAgB,kCAAkC,UAAU,yBAAyB,YAAY,mCAAmC,sCAAsC,mCAAmC,YAAY,mCAAmC,sCAAsC,mCAAmC,SAAS,mCAAmC,gCAAgC,mCAAmC,YAAY,mCAAmC,sCAAsC,mCAAmC,WAAW,mCAAmC,oCAAoC,mCAAmC,YAAY,mCAAmC,sCAAsC,mCAAmC,UAAU,mBAAmB,cAAc,uBAAuB,gBAAgB,yBAAyB,iBAAiB,0BAA0B,eAAe,wBAAwB,SAAS,qBAAqB,aAAa,+BAA+B,8BAA8B,eAAe,kCAAkC,+BAA+B,gBAAgB,kCAAkC,iCAAiC,cAAc,iCAAiC,8BAA8B,gBAAgB,kBAAkB,WAAW,gBAAgB,iBAAiB,cAAc,aAAa,WAAW,QAAQ,uBAAuB,UAAU,yBAAyB,gBAAgB,+BAA+B,SAAS,wBAAwB,SAAS,wBAAwB,cAAc,6BAA6B,QAAQ,8BAA8B,8BAA8B,uBAAuB,eAAe,qCAAqC,qCAAqC,8BAA8B,yBAAyB,WAAW,uBAAuB,aAAa,yBAAyB,mBAAmB,+BAA+B,YAAY,wBAAwB,YAAY,wBAAwB,iBAAiB,6BAA6B,WAAW,8BAA8B,8BAA8B,uBAAuB,kBAAkB,qCAAqC,qCAAqC,+BAA+B,yBAAyB,WAAW,uBAAuB,aAAa,yBAAyB,mBAAmB,+BAA+B,YAAY,wBAAwB,YAAY,wBAAwB,iBAAiB,6BAA6B,WAAW,8BAA8B,8BAA8B,uBAAuB,kBAAkB,qCAAqC,qCAAqC,+BAA+B,yBAAyB,WAAW,uBAAuB,aAAa,yBAAyB,mBAAmB,+BAA+B,YAAY,wBAAwB,YAAY,wBAAwB,iBAAiB,6BAA6B,WAAW,8BAA8B,8BAA8B,uBAAuB,kBAAkB,qCAAqC,qCAAqC,+BAA+B,0BAA0B,WAAW,uBAAuB,aAAa,yBAAyB,mBAAmB,+BAA+B,YAAY,wBAAwB,YAAY,wBAAwB,iBAAiB,6BAA6B,WAAW,8BAA8B,8BAA8B,uBAAuB,kBAAkB,qCAAqC,qCAAqC,+BAA+B,YAAY,4BAA4B,kBAAkB,SAAS,WAAW,4BAA4B,iBAAiB,QAAQ,gBAAgB,4BAA4B,iBAAiB,QAAQ,UAAU,wCAAwC,uCAAuC,iCAAiC,6BAA6B,aAAa,sCAAsC,uCAAuC,oCAAoC,gCAAgC,kBAAkB,wCAAwC,wCAAwC,yCAAyC,qCAAqC,qBAAqB,sCAAsC,wCAAwC,4CAA4C,wCAAwC,WAAW,6BAA6B,yBAAyB,aAAa,+BAA+B,2BAA2B,mBAAmB,qCAAqC,iCAAiC,uBAAuB,iCAAiC,8BAA8B,qCAAqC,qBAAqB,+BAA+B,4BAA4B,mCAAmC,wBAAwB,kCAAkC,+BAA+B,iCAAiC,yBAAyB,mCAAmC,gCAAgC,wCAAwC,wBAAwB,mCAAmC,uCAAuC,mBAAmB,kCAAkC,+BAA+B,iCAAiC,iBAAiB,gCAAgC,6BAA6B,+BAA+B,oBAAoB,mCAAmC,gCAAgC,6BAA6B,sBAAsB,qCAAqC,kCAAkC,+BAA+B,qBAAqB,oCAAoC,iCAAiC,8BAA8B,qBAAqB,mCAAmC,mCAAmC,mBAAmB,iCAAiC,iCAAiC,sBAAsB,oCAAoC,+BAA+B,uBAAuB,qCAAqC,sCAAsC,sBAAsB,wCAAwC,qCAAqC,uBAAuB,qCAAqC,gCAAgC,iBAAiB,kCAAkC,mCAAmC,kCAAkC,0BAA0B,kBAAkB,wCAAwC,oCAAoC,gCAAgC,gBAAgB,sCAAsC,kCAAkC,8BAA8B,mBAAmB,oCAAoC,qCAAqC,oCAAoC,4BAA4B,qBAAqB,sCAAsC,uCAAuC,8BAA8B,oBAAoB,qCAAqC,sCAAsC,qCAAqC,6BAA6B,yBAAyB,eAAe,4BAA4B,kBAAkB,SAAS,cAAc,4BAA4B,iBAAiB,QAAQ,mBAAmB,4BAA4B,iBAAiB,QAAQ,aAAa,wCAAwC,uCAAuC,iCAAiC,6BAA6B,gBAAgB,sCAAsC,uCAAuC,oCAAoC,gCAAgC,qBAAqB,wCAAwC,wCAAwC,yCAAyC,qCAAqC,wBAAwB,sCAAsC,wCAAwC,4CAA4C,wCAAwC,cAAc,6BAA6B,yBAAyB,gBAAgB,+BAA+B,2BAA2B,sBAAsB,qCAAqC,iCAAiC,0BAA0B,iCAAiC,8BAA8B,qCAAqC,wBAAwB,+BAA+B,4BAA4B,mCAAmC,2BAA2B,kCAAkC,+BAA+B,iCAAiC,4BAA4B,mCAAmC,gCAAgC,wCAAwC,2BAA2B,mCAAmC,uCAAuC,sBAAsB,kCAAkC,+BAA+B,iCAAiC,oBAAoB,gCAAgC,6BAA6B,+BAA+B,uBAAuB,mCAAmC,gCAAgC,6BAA6B,yBAAyB,qCAAqC,kCAAkC,+BAA+B,wBAAwB,oCAAoC,iCAAiC,8BAA8B,wBAAwB,mCAAmC,mCAAmC,sBAAsB,iCAAiC,iCAAiC,yBAAyB,oCAAoC,+BAA+B,0BAA0B,qCAAqC,sCAAsC,yBAAyB,wCAAwC,qCAAqC,0BAA0B,qCAAqC,gCAAgC,oBAAoB,kCAAkC,mCAAmC,kCAAkC,0BAA0B,qBAAqB,wCAAwC,oCAAoC,gCAAgC,mBAAmB,sCAAsC,kCAAkC,8BAA8B,sBAAsB,oCAAoC,qCAAqC,oCAAoC,4BAA4B,wBAAwB,sCAAsC,uCAAuC,8BAA8B,uBAAuB,qCAAqC,sCAAsC,qCAAqC,8BAA8B,yBAAyB,eAAe,4BAA4B,kBAAkB,SAAS,cAAc,4BAA4B,iBAAiB,QAAQ,mBAAmB,4BAA4B,iBAAiB,QAAQ,aAAa,wCAAwC,uCAAuC,iCAAiC,6BAA6B,gBAAgB,sCAAsC,uCAAuC,oCAAoC,gCAAgC,qBAAqB,wCAAwC,wCAAwC,yCAAyC,qCAAqC,wBAAwB,sCAAsC,wCAAwC,4CAA4C,wCAAwC,cAAc,6BAA6B,yBAAyB,gBAAgB,+BAA+B,2BAA2B,sBAAsB,qCAAqC,iCAAiC,0BAA0B,iCAAiC,8BAA8B,qCAAqC,wBAAwB,+BAA+B,4BAA4B,mCAAmC,2BAA2B,kCAAkC,+BAA+B,iCAAiC,4BAA4B,mCAAmC,gCAAgC,wCAAwC,2BAA2B,mCAAmC,uCAAuC,sBAAsB,kCAAkC,+BAA+B,iCAAiC,oBAAoB,gCAAgC,6BAA6B,+BAA+B,uBAAuB,mCAAmC,gCAAgC,6BAA6B,yBAAyB,qCAAqC,kCAAkC,+BAA+B,wBAAwB,oCAAoC,iCAAiC,8BAA8B,wBAAwB,mCAAmC,mCAAmC,sBAAsB,iCAAiC,iCAAiC,yBAAyB,oCAAoC,+BAA+B,0BAA0B,qCAAqC,sCAAsC,yBAAyB,wCAAwC,qCAAqC,0BAA0B,qCAAqC,gCAAgC,oBAAoB,kCAAkC,mCAAmC,kCAAkC,0BAA0B,qBAAqB,wCAAwC,oCAAoC,gCAAgC,mBAAmB,sCAAsC,kCAAkC,8BAA8B,sBAAsB,oCAAoC,qCAAqC,oCAAoC,4BAA4B,wBAAwB,sCAAsC,uCAAuC,8BAA8B,uBAAuB,qCAAqC,sCAAsC,qCAAqC,8BAA8B,yBAAyB,eAAe,4BAA4B,kBAAkB,SAAS,cAAc,4BAA4B,iBAAiB,QAAQ,mBAAmB,4BAA4B,iBAAiB,QAAQ,aAAa,wCAAwC,uCAAuC,iCAAiC,6BAA6B,gBAAgB,sCAAsC,uCAAuC,oCAAoC,gCAAgC,qBAAqB,wCAAwC,wCAAwC,yCAAyC,qCAAqC,wBAAwB,sCAAsC,wCAAwC,4CAA4C,wCAAwC,cAAc,6BAA6B,yBAAyB,gBAAgB,+BAA+B,2BAA2B,sBAAsB,qCAAqC,iCAAiC,0BAA0B,iCAAiC,8BAA8B,qCAAqC,wBAAwB,+BAA+B,4BAA4B,mCAAmC,2BAA2B,kCAAkC,+BAA+B,iCAAiC,4BAA4B,mCAAmC,gCAAgC,wCAAwC,2BAA2B,mCAAmC,uCAAuC,sBAAsB,kCAAkC,+BAA+B,iCAAiC,oBAAoB,gCAAgC,6BAA6B,+BAA+B,uBAAuB,mCAAmC,gCAAgC,6BAA6B,yBAAyB,qCAAqC,kCAAkC,+BAA+B,wBAAwB,oCAAoC,iCAAiC,8BAA8B,wBAAwB,mCAAmC,mCAAmC,sBAAsB,iCAAiC,iCAAiC,yBAAyB,oCAAoC,+BAA+B,0BAA0B,qCAAqC,sCAAsC,yBAAyB,wCAAwC,qCAAqC,0BAA0B,qCAAqC,gCAAgC,oBAAoB,kCAAkC,mCAAmC,kCAAkC,0BAA0B,qBAAqB,wCAAwC,oCAAoC,gCAAgC,mBAAmB,sCAAsC,kCAAkC,8BAA8B,sBAAsB,oCAAoC,qCAAqC,oCAAoC,4BAA4B,wBAAwB,sCAAsC,uCAAuC,8BAA8B,uBAAuB,qCAAqC,sCAAsC,qCAAqC,8BAA8B,0BAA0B,eAAe,4BAA4B,kBAAkB,SAAS,cAAc,4BAA4B,iBAAiB,QAAQ,mBAAmB,4BAA4B,iBAAiB,QAAQ,aAAa,wCAAwC,uCAAuC,iCAAiC,6BAA6B,gBAAgB,sCAAsC,uCAAuC,oCAAoC,gCAAgC,qBAAqB,wCAAwC,wCAAwC,yCAAyC,qCAAqC,wBAAwB,sCAAsC,wCAAwC,4CAA4C,wCAAwC,cAAc,6BAA6B,yBAAyB,gBAAgB,+BAA+B,2BAA2B,sBAAsB,qCAAqC,iCAAiC,0BAA0B,iCAAiC,8BAA8B,qCAAqC,wBAAwB,+BAA+B,4BAA4B,mCAAmC,2BAA2B,kCAAkC,+BAA+B,iCAAiC,4BAA4B,mCAAmC,gCAAgC,wCAAwC,2BAA2B,mCAAmC,uCAAuC,sBAAsB,kCAAkC,+BAA+B,iCAAiC,oBAAoB,gCAAgC,6BAA6B,+BAA+B,uBAAuB,mCAAmC,gCAAgC,6BAA6B,yBAAyB,qCAAqC,kCAAkC,+BAA+B,wBAAwB,oCAAoC,iCAAiC,8BAA8B,wBAAwB,mCAAmC,mCAAmC,sBAAsB,iCAAiC,iCAAiC,yBAAyB,oCAAoC,+BAA+B,0BAA0B,qCAAqC,sCAAsC,yBAAyB,wCAAwC,qCAAqC,0BAA0B,qCAAqC,gCAAgC,oBAAoB,kCAAkC,mCAAmC,kCAAkC,0BAA0B,qBAAqB,wCAAwC,oCAAoC,gCAAgC,mBAAmB,sCAAsC,kCAAkC,8BAA8B,sBAAsB,oCAAoC,qCAAqC,oCAAoC,4BAA4B,wBAAwB,sCAAsC,uCAAuC,8BAA8B,uBAAuB,qCAAqC,sCAAsC,qCAAqC,8BAA8B,YAAY,qBAAqB,aAAa,sBAAsB,YAAY,qBAAqB,yBAAyB,eAAe,qBAAqB,gBAAgB,sBAAsB,eAAe,sBAAsB,yBAAyB,eAAe,qBAAqB,gBAAgB,sBAAsB,eAAe,sBAAsB,yBAAyB,eAAe,qBAAqB,gBAAgB,sBAAsB,eAAe,sBAAsB,0BAA0B,eAAe,qBAAqB,gBAAgB,sBAAsB,eAAe,sBAAsB,WAAW,eAAe,MAAM,QAAQ,OAAO,aAAa,cAAc,eAAe,QAAQ,SAAS,OAAO,aAAa,YAAY,wBAAwB,gBAAgB,MAAM,aAAa,SAAS,kBAAkB,UAAU,WAAW,UAAU,YAAY,gBAAgB,mBAAmB,SAAS,mDAAmD,gBAAgB,WAAW,YAAY,SAAS,iBAAiB,UAAU,MAAM,oBAAoB,MAAM,oBAAoB,MAAM,oBAAoB,OAAO,qBAAqB,MAAM,qBAAqB,MAAM,qBAAqB,MAAM,qBAAqB,OAAO,sBAAsB,QAAQ,yBAAyB,QAAQ,0BAA0B,KAAK,qBAAqB,MAAM,uBAAuB,MAAM,yBAAyB,MAAM,0BAA0B,MAAM,wBAAwB,MAAM,yBAAyB,wBAAwB,MAAM,uBAAuB,0BAA0B,KAAK,+BAA+B,MAAM,4BAA4B,MAAM,8BAA8B,MAAM,+BAA+B,MAAM,6BAA6B,MAAM,8BAA8B,6BAA6B,MAAM,4BAA4B,+BAA+B,KAAK,6BAA6B,MAAM,2BAA2B,MAAM,6BAA6B,MAAM,8BAA8B,MAAM,4BAA4B,MAAM,6BAA6B,4BAA4B,MAAM,2BAA2B,8BAA8B,KAAK,2BAA2B,MAAM,0BAA0B,MAAM,4BAA4B,MAAM,6BAA6B,MAAM,2BAA2B,MAAM,4BAA4B,2BAA2B,MAAM,0BAA0B,6BAA6B,KAAK,+BAA+B,MAAM,4BAA4B,MAAM,8BAA8B,MAAM,+BAA+B,MAAM,6BAA6B,MAAM,8BAA8B,6BAA6B,MAAM,4BAA4B,+BAA+B,KAAK,2BAA2B,MAAM,0BAA0B,MAAM,4BAA4B,MAAM,6BAA6B,MAAM,2BAA2B,MAAM,4BAA4B,2BAA2B,MAAM,0BAA0B,6BAA6B,KAAK,sBAAsB,MAAM,wBAAwB,MAAM,0BAA0B,MAAM,2BAA2B,MAAM,yBAAyB,MAAM,0BAA0B,yBAAyB,MAAM,wBAAwB,2BAA2B,KAAK,gCAAgC,MAAM,6BAA6B,MAAM,+BAA+B,MAAM,gCAAgC,MAAM,8BAA8B,MAAM,+BAA+B,8BAA8B,MAAM,6BAA6B,gCAAgC,KAAK,8BAA8B,MAAM,4BAA4B,MAAM,8BAA8B,MAAM,+BAA+B,MAAM,6BAA6B,MAAM,8BAA8B,6BAA6B,MAAM,4BAA4B,+BAA+B,KAAK,4BAA4B,MAAM,2BAA2B,MAAM,6BAA6B,MAAM,8BAA8B,MAAM,4BAA4B,MAAM,6BAA6B,4BAA4B,MAAM,2BAA2B,8BAA8B,KAAK,gCAAgC,MAAM,6BAA6B,MAAM,+BAA+B,MAAM,gCAAgC,MAAM,8BAA8B,MAAM,+BAA+B,8BAA8B,MAAM,6BAA6B,gCAAgC,KAAK,4BAA4B,MAAM,2BAA2B,MAAM,6BAA6B,MAAM,8BAA8B,MAAM,4BAA4B,MAAM,6BAA6B,4BAA4B,MAAM,2BAA2B,8BAA8B,QAAQ,sBAAsB,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,yBAAyB,QAAQ,qBAAqB,SAAS,uBAAuB,SAAS,yBAAyB,SAAS,0BAA0B,SAAS,wBAAwB,SAAS,yBAAyB,wBAAwB,SAAS,uBAAuB,0BAA0B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,6BAA6B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,sBAAsB,SAAS,wBAAwB,SAAS,0BAA0B,SAAS,2BAA2B,SAAS,yBAAyB,SAAS,0BAA0B,yBAAyB,SAAS,wBAAwB,2BAA2B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,8BAA8B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,WAAW,sBAAsB,YAAY,0BAA0B,YAAY,4BAA4B,YAAY,6BAA6B,YAAY,2BAA2B,YAAY,4BAA4B,2BAA2B,YAAY,0BAA0B,8BAA8B,yBAAyB,QAAQ,qBAAqB,SAAS,uBAAuB,SAAS,yBAAyB,SAAS,0BAA0B,SAAS,wBAAwB,SAAS,yBAAyB,wBAAwB,SAAS,uBAAuB,0BAA0B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,6BAA6B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,sBAAsB,SAAS,wBAAwB,SAAS,0BAA0B,SAAS,2BAA2B,SAAS,yBAAyB,SAAS,0BAA0B,yBAAyB,SAAS,wBAAwB,2BAA2B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,8BAA8B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,WAAW,sBAAsB,YAAY,0BAA0B,YAAY,4BAA4B,YAAY,6BAA6B,YAAY,2BAA2B,YAAY,4BAA4B,2BAA2B,YAAY,0BAA0B,8BAA8B,yBAAyB,QAAQ,qBAAqB,SAAS,uBAAuB,SAAS,yBAAyB,SAAS,0BAA0B,SAAS,wBAAwB,SAAS,yBAAyB,wBAAwB,SAAS,uBAAuB,0BAA0B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,6BAA6B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,sBAAsB,SAAS,wBAAwB,SAAS,0BAA0B,SAAS,2BAA2B,SAAS,yBAAyB,SAAS,0BAA0B,yBAAyB,SAAS,wBAAwB,2BAA2B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,8BAA8B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,WAAW,sBAAsB,YAAY,0BAA0B,YAAY,4BAA4B,YAAY,6BAA6B,YAAY,2BAA2B,YAAY,4BAA4B,2BAA2B,YAAY,0BAA0B,8BAA8B,0BAA0B,QAAQ,qBAAqB,SAAS,uBAAuB,SAAS,yBAAyB,SAAS,0BAA0B,SAAS,wBAAwB,SAAS,yBAAyB,wBAAwB,SAAS,uBAAuB,0BAA0B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,6BAA6B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,+BAA+B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,2BAA2B,SAAS,0BAA0B,SAAS,4BAA4B,SAAS,6BAA6B,SAAS,2BAA2B,SAAS,4BAA4B,2BAA2B,SAAS,0BAA0B,6BAA6B,QAAQ,sBAAsB,SAAS,wBAAwB,SAAS,0BAA0B,SAAS,2BAA2B,SAAS,yBAAyB,SAAS,0BAA0B,yBAAyB,SAAS,wBAAwB,2BAA2B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,8BAA8B,SAAS,4BAA4B,SAAS,8BAA8B,SAAS,+BAA+B,SAAS,6BAA6B,SAAS,8BAA8B,6BAA6B,SAAS,4BAA4B,+BAA+B,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,QAAQ,gCAAgC,SAAS,6BAA6B,SAAS,+BAA+B,SAAS,gCAAgC,SAAS,8BAA8B,SAAS,+BAA+B,8BAA8B,SAAS,6BAA6B,gCAAgC,QAAQ,4BAA4B,SAAS,2BAA2B,SAAS,6BAA6B,SAAS,8BAA8B,SAAS,4BAA4B,SAAS,6BAA6B,4BAA4B,SAAS,2BAA2B,8BAA8B,WAAW,sBAAsB,YAAY,0BAA0B,YAAY,4BAA4B,YAAY,6BAA6B,YAAY,2BAA2B,YAAY,4BAA4B,2BAA2B,YAAY,0BAA0B,8BAA8B,cAAc,6BAA6B,aAAa,6BAA6B,eAAe,gBAAgB,uBAAuB,mBAAmB,WAAW,0BAA0B,YAAY,2BAA2B,aAAa,4BAA4B,yBAAyB,cAAc,0BAA0B,eAAe,2BAA2B,gBAAgB,6BAA6B,yBAAyB,cAAc,0BAA0B,eAAe,2BAA2B,gBAAgB,6BAA6B,yBAAyB,cAAc,0BAA0B,eAAe,2BAA2B,gBAAgB,6BAA6B,0BAA0B,cAAc,0BAA0B,eAAe,2BAA2B,gBAAgB,6BAA6B,gBAAgB,mCAAmC,gBAAgB,mCAAmC,iBAAiB,oCAAoC,oBAAoB,gBAAgB,kBAAkB,gBAAgB,aAAa,kBAAkB,YAAY,qBAAqB,YAAY,wBAAwB,sCAAsC,wBAAwB,cAAc,wBAAwB,0CAA0C,wBAAwB,cAAc,wBAAwB,0CAA0C,wBAAwB,WAAW,wBAAwB,oCAAoC,wBAAwB,cAAc,wBAAwB,0CAA0C,wBAAwB,aAAa,wBAAwB,wCAAwC,wBAAwB,gBAAgB,wBAAwB,8CAA8C,wBAAwB,WAAW,WAAW,kBAAkB,iBAAiB,6BAA6B,SAAS,WAAW,4BAA4B,cAAc,uBAAuB,yBAAyB,gBAAgB,wBAAwB,yBAAyB,cAAc,wBAAwB,yBAAyB,gBAAgB,wBAAwB,yBAAyB,cAAc,wBAAwB,yBAAyB,gBAAgB,wBAAwB,yBAAyB,cAAc,wBAAwB,0BAA0B,gBAAgB,wBAAwB,0BAA0B,cAAc,wBAAwB,gBAAgB,uBAAuB,qBAAqB,uBAAuB,aAAa,qBAAqB,yBAAyB,sBAAsB,uBAAuB,aAAa,sBAAsB,0BAA0B,4BAA4B,uBAAuB,aAAa,4BAA4B,gCAAgC,aAAa,cAAc,wBAAwB;;AAEz5vI;;;;;;;;ACPA;AACA;;;AAGA;AACA;;AAEA;;;;;;;;;;;;;;;;;ACPA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA,EAAE;AACF;AACA;AACA,EAAE;AACF;AACA;AACA,EAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,gBAAgB,mBAAmB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,sBAAsB;AACtC;AACA;AACA,kBAAkB,2BAA2B;AAC7C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,eAAe,mBAAmB;AAClC;AACA;AACA;AACA;AACA,iBAAiB,2BAA2B;AAC5C;AACA;AACA,QAAQ,uBAAuB;AAC/B;AACA;AACA,GAAG;AACH;AACA,iBAAiB,uBAAuB;AACxC;AACA;AACA,2BAA2B;AAC3B;AACA;AACA;;AAEA;AACA;AACA;AACA,eAAe,iBAAiB;AAChC;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA,gCAAgC,sBAAsB;AACtD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA;AACA,EAAE;AACF;AACA,EAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;;AAEA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uDAAuD;AACvD;;AAEA,6BAA6B,mBAAmB;;AAEhD;;AAEA;;AAEA;AACA;AACA;;;;;;;;ACrPA;;AAEA;AACA,qCAA+F;AAC/F;AACA;AACA,gDAAuE;AACvE;AACA;AACA;AACA;AACA;AACA,qDAAqD,wCAAwC;AAC7F,6DAA6D,wCAAwC;AACrG;AACA;AACA,GAAG;AACH;AACA;AACA,gCAAgC,UAAU,EAAE;AAC5C,C;;;;;;;ACpBA;;AAEA;AACA,qCAAsG;AACtG;AACA;AACA,gDAA8E;AAC9E;AACA;AACA;AACA;AACA;AACA,4DAA4D,wCAAwC;AACpG,oEAAoE,wCAAwC;AAC5G;AACA;AACA,GAAG;AACH;AACA;AACA,gCAAgC,UAAU,EAAE;AAC5C,C","file":"styles.bundle.js","sourcesContent":["/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function() {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\tvar result = [];\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar item = this[i];\n\t\t\tif(item[2]) {\n\t\t\t\tresult.push(\"@media \" + item[2] + \"{\" + item[1] + \"}\");\n\t\t\t} else {\n\t\t\t\tresult.push(item[1]);\n\t\t\t}\n\t\t}\n\t\treturn result.join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/css-loader/lib/css-base.js\n// module id = 13\n// module chunks = 2 3","exports = module.exports = require(\"../../../css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \"/*!\\n * Bootstrap v4.0.0-alpha.6 (https://getbootstrap.com)\\n * Copyright 2011-2017 The Bootstrap Authors\\n * Copyright 2011-2017 Twitter, Inc.\\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\\n *//*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}@media print{*,::after,::before,blockquote::first-letter,blockquote::first-line,div::first-letter,div::first-line,li::first-letter,li::first-line,p::first-letter,p::first-line{text-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}abbr[title]::after{content:\\\" (\\\" attr(title) \\\")\\\"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}html{box-sizing:border-box}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}html{-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,\\\"Segoe UI\\\",Roboto,\\\"Helvetica Neue\\\",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#292b2c;background-color:#fff}[tabindex=\\\"-1\\\"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#636c72;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.1}.display-2{font-size:5.5rem;font-weight:300;line-height:1.1}.display-3{font-size:4.5rem;font-weight:300;line-height:1.1}.display-4{font-size:3.5rem;font-weight:300;line-height:1.1}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:5px}.initialism{font-size:90%;text-transform:uppercase}.blockquote{padding:.5rem 1rem;margin-bottom:1rem;font-size:1.25rem;border-left:.25rem solid #eceeef}.blockquote-footer{display:block;font-size:80%;color:#636c72}.blockquote-footer::before{content:\\\"\\\\2014 \\\\A0\\\"}.blockquote-reverse{padding-right:1rem;padding-left:0;text-align:right;border-right:.25rem solid #eceeef;border-left:0}.blockquote-reverse .blockquote-footer::before{content:\\\"\\\"}.blockquote-reverse .blockquote-footer::after{content:\\\"\\\\A0 \\\\2014\\\"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #ddd;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#636c72}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace}code{padding:.2rem .4rem;font-size:90%;color:#bd4147;background-color:#f7f7f9;border-radius:.25rem}a>code{padding:0;color:inherit;background-color:inherit}kbd{padding:.2rem .4rem;font-size:90%;color:#fff;background-color:#292b2c;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;margin-top:0;margin-bottom:1rem;font-size:90%;color:#292b2c}pre code{padding:0;font-size:inherit;color:inherit;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{position:relative;margin-left:auto;margin-right:auto;padding-right:15px;padding-left:15px}@media (min-width:576px){.container{padding-right:15px;padding-left:15px}}@media (min-width:768px){.container{padding-right:15px;padding-left:15px}}@media (min-width:992px){.container{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.container{padding-right:15px;padding-left:15px}}@media (min-width:576px){.container{width:540px;max-width:100%}}@media (min-width:768px){.container{width:720px;max-width:100%}}@media (min-width:992px){.container{width:960px;max-width:100%}}@media (min-width:1200px){.container{width:1140px;max-width:100%}}.container-fluid{position:relative;margin-left:auto;margin-right:auto;padding-right:15px;padding-left:15px}@media (min-width:576px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:768px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:992px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.container-fluid{padding-right:15px;padding-left:15px}}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}@media (min-width:576px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:768px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:992px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:1200px){.row{margin-right:-15px;margin-left:-15px}}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}@media (min-width:576px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:768px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:992px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-0{right:auto}.pull-1{right:8.333333%}.pull-2{right:16.666667%}.pull-3{right:25%}.pull-4{right:33.333333%}.pull-5{right:41.666667%}.pull-6{right:50%}.pull-7{right:58.333333%}.pull-8{right:66.666667%}.pull-9{right:75%}.pull-10{right:83.333333%}.pull-11{right:91.666667%}.pull-12{right:100%}.push-0{left:auto}.push-1{left:8.333333%}.push-2{left:16.666667%}.push-3{left:25%}.push-4{left:33.333333%}.push-5{left:41.666667%}.push-6{left:50%}.push-7{left:58.333333%}.push-8{left:66.666667%}.push-9{left:75%}.push-10{left:83.333333%}.push-11{left:91.666667%}.push-12{left:100%}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-sm-0{right:auto}.pull-sm-1{right:8.333333%}.pull-sm-2{right:16.666667%}.pull-sm-3{right:25%}.pull-sm-4{right:33.333333%}.pull-sm-5{right:41.666667%}.pull-sm-6{right:50%}.pull-sm-7{right:58.333333%}.pull-sm-8{right:66.666667%}.pull-sm-9{right:75%}.pull-sm-10{right:83.333333%}.pull-sm-11{right:91.666667%}.pull-sm-12{right:100%}.push-sm-0{left:auto}.push-sm-1{left:8.333333%}.push-sm-2{left:16.666667%}.push-sm-3{left:25%}.push-sm-4{left:33.333333%}.push-sm-5{left:41.666667%}.push-sm-6{left:50%}.push-sm-7{left:58.333333%}.push-sm-8{left:66.666667%}.push-sm-9{left:75%}.push-sm-10{left:83.333333%}.push-sm-11{left:91.666667%}.push-sm-12{left:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-md-0{right:auto}.pull-md-1{right:8.333333%}.pull-md-2{right:16.666667%}.pull-md-3{right:25%}.pull-md-4{right:33.333333%}.pull-md-5{right:41.666667%}.pull-md-6{right:50%}.pull-md-7{right:58.333333%}.pull-md-8{right:66.666667%}.pull-md-9{right:75%}.pull-md-10{right:83.333333%}.pull-md-11{right:91.666667%}.pull-md-12{right:100%}.push-md-0{left:auto}.push-md-1{left:8.333333%}.push-md-2{left:16.666667%}.push-md-3{left:25%}.push-md-4{left:33.333333%}.push-md-5{left:41.666667%}.push-md-6{left:50%}.push-md-7{left:58.333333%}.push-md-8{left:66.666667%}.push-md-9{left:75%}.push-md-10{left:83.333333%}.push-md-11{left:91.666667%}.push-md-12{left:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-lg-0{right:auto}.pull-lg-1{right:8.333333%}.pull-lg-2{right:16.666667%}.pull-lg-3{right:25%}.pull-lg-4{right:33.333333%}.pull-lg-5{right:41.666667%}.pull-lg-6{right:50%}.pull-lg-7{right:58.333333%}.pull-lg-8{right:66.666667%}.pull-lg-9{right:75%}.pull-lg-10{right:83.333333%}.pull-lg-11{right:91.666667%}.pull-lg-12{right:100%}.push-lg-0{left:auto}.push-lg-1{left:8.333333%}.push-lg-2{left:16.666667%}.push-lg-3{left:25%}.push-lg-4{left:33.333333%}.push-lg-5{left:41.666667%}.push-lg-6{left:50%}.push-lg-7{left:58.333333%}.push-lg-8{left:66.666667%}.push-lg-9{left:75%}.push-lg-10{left:83.333333%}.push-lg-11{left:91.666667%}.push-lg-12{left:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-xl-0{right:auto}.pull-xl-1{right:8.333333%}.pull-xl-2{right:16.666667%}.pull-xl-3{right:25%}.pull-xl-4{right:33.333333%}.pull-xl-5{right:41.666667%}.pull-xl-6{right:50%}.pull-xl-7{right:58.333333%}.pull-xl-8{right:66.666667%}.pull-xl-9{right:75%}.pull-xl-10{right:83.333333%}.pull-xl-11{right:91.666667%}.pull-xl-12{right:100%}.push-xl-0{left:auto}.push-xl-1{left:8.333333%}.push-xl-2{left:16.666667%}.push-xl-3{left:25%}.push-xl-4{left:33.333333%}.push-xl-5{left:41.666667%}.push-xl-6{left:50%}.push-xl-7{left:58.333333%}.push-xl-8{left:66.666667%}.push-xl-9{left:75%}.push-xl-10{left:83.333333%}.push-xl-11{left:91.666667%}.push-xl-12{left:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #eceeef}.table thead th{vertical-align:bottom;border-bottom:2px solid #eceeef}.table tbody+tbody{border-top:2px solid #eceeef}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #eceeef}.table-bordered td,.table-bordered th{border:1px solid #eceeef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table-success,.table-success>td,.table-success>th{background-color:#dff0d8}.table-hover .table-success:hover{background-color:#d0e9c6}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#d0e9c6}.table-info,.table-info>td,.table-info>th{background-color:#d9edf7}.table-hover .table-info:hover{background-color:#c4e3f3}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#c4e3f3}.table-warning,.table-warning>td,.table-warning>th{background-color:#fcf8e3}.table-hover .table-warning:hover{background-color:#faf2cc}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#faf2cc}.table-danger,.table-danger>td,.table-danger>th{background-color:#f2dede}.table-hover .table-danger:hover{background-color:#ebcccc}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#ebcccc}.thead-inverse th{color:#fff;background-color:#292b2c}.thead-default th{color:#464a4c;background-color:#eceeef}.table-inverse{color:#fff;background-color:#292b2c}.table-inverse td,.table-inverse th,.table-inverse thead th{border-color:#fff}.table-inverse.table-bordered{border:0}.table-responsive{display:block;width:100%;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive.table-bordered{border:0}.form-control{display:block;width:100%;padding:.5rem .75rem;font-size:1rem;line-height:1.25;color:#464a4c;background-color:#fff;background-image:none;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#464a4c;background-color:#fff;border-color:#5cb3fd;outline:0}.form-control::-webkit-input-placeholder{color:#636c72;opacity:1}.form-control:-ms-input-placeholder{color:#636c72;opacity:1}.form-control::placeholder{color:#636c72;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eceeef;opacity:1}.form-control:disabled{cursor:not-allowed}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#464a4c;background-color:#fff}.form-control-file,.form-control-range{display:block}.col-form-label{padding-top:calc(.5rem - 1px * 2);padding-bottom:calc(.5rem - 1px * 2);margin-bottom:0}.col-form-label-lg{padding-top:calc(.75rem - 1px * 2);padding-bottom:calc(.75rem - 1px * 2);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem - 1px * 2);padding-bottom:calc(.25rem - 1px * 2);font-size:.875rem}.col-form-legend{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;font-size:1rem}.form-control-static{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;line-height:1.25;border:solid transparent;border-width:1px 0}.form-control-static.form-control-lg,.form-control-static.form-control-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>select.input-group-addon:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:1.8125rem}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>select.input-group-addon:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:3.166667rem}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-check{position:relative;display:block;margin-bottom:.5rem}.form-check.disabled .form-check-label{color:#636c72;cursor:not-allowed}.form-check-label{padding-left:1.25rem;margin-bottom:0;cursor:pointer}.form-check-input{position:absolute;margin-top:.25rem;margin-left:-1.25rem}.form-check-input:only-child{position:static}.form-check-inline{display:inline-block}.form-check-inline .form-check-label{vertical-align:middle}.form-check-inline+.form-check-inline{margin-left:.75rem}.form-control-feedback{margin-top:.25rem}.form-control-danger,.form-control-success,.form-control-warning{padding-right:2.25rem;background-repeat:no-repeat;background-position:center right .5625rem;background-size:1.125rem 1.125rem}.has-success .col-form-label,.has-success .custom-control,.has-success .form-check-label,.has-success .form-control-feedback,.has-success .form-control-label{color:#5cb85c}.has-success .form-control{border-color:#5cb85c}.has-success .input-group-addon{color:#5cb85c;border-color:#5cb85c;background-color:#eaf6ea}.has-success .form-control-success{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E\\\")}.has-warning .col-form-label,.has-warning .custom-control,.has-warning .form-check-label,.has-warning .form-control-feedback,.has-warning .form-control-label{color:#f0ad4e}.has-warning .form-control{border-color:#f0ad4e}.has-warning .input-group-addon{color:#f0ad4e;border-color:#f0ad4e;background-color:#fff}.has-warning .form-control-warning{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E\\\")}.has-danger .col-form-label,.has-danger .custom-control,.has-danger .form-check-label,.has-danger .form-control-feedback,.has-danger .form-control-label{color:#d9534f}.has-danger .form-control{border-color:#d9534f}.has-danger .input-group-addon{color:#d9534f;border-color:#d9534f;background-color:#fdf7f7}.has-danger .form-control-danger{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E\\\")}.form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{width:auto}.form-inline .form-control-label{margin-bottom:0;vertical-align:middle}.form-inline .form-check{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:auto;margin-top:0;margin-bottom:0}.form-inline .form-check-label{padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0}.form-inline .custom-control-indicator{position:static;display:inline-block;margin-right:.25rem;vertical-align:text-bottom}.form-inline .has-feedback .form-control-feedback{top:0}}.btn{display:inline-block;font-weight:400;line-height:1.25;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem 1rem;font-size:1rem;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 2px rgba(2,117,216,.25)}.btn.disabled,.btn:disabled{cursor:not-allowed;opacity:.65}.btn.active,.btn:active{background-image:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-primary:hover{color:#fff;background-color:#025aa5;border-color:#01549b}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 2px rgba(2,117,216,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#0275d8;border-color:#0275d8}.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#025aa5;background-image:none;border-color:#01549b}.btn-secondary{color:#292b2c;background-color:#fff;border-color:#ccc}.btn-secondary:hover{color:#292b2c;background-color:#e6e6e6;border-color:#adadad}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 2px rgba(204,204,204,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#fff;border-color:#ccc}.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#292b2c;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 2px rgba(91,192,222,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#5bc0de;border-color:#5bc0de}.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;background-image:none;border-color:#2aabd2}.btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#419641}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 2px rgba(92,184,92,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#5cb85c;border-color:#5cb85c}.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;background-image:none;border-color:#419641}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#eb9316}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 2px rgba(240,173,78,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;background-image:none;border-color:#eb9316}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#c12e2a}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 2px rgba(217,83,79,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#d9534f;border-color:#d9534f}.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;background-image:none;border-color:#c12e2a}.btn-outline-primary{color:#0275d8;background-image:none;background-color:transparent;border-color:#0275d8}.btn-outline-primary:hover{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 2px rgba(2,117,216,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#0275d8;background-color:transparent}.btn-outline-primary.active,.btn-outline-primary:active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-secondary{color:#ccc;background-image:none;background-color:transparent;border-color:#ccc}.btn-outline-secondary:hover{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 2px rgba(204,204,204,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#ccc;background-color:transparent}.btn-outline-secondary.active,.btn-outline-secondary:active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-info{color:#5bc0de;background-image:none;background-color:transparent;border-color:#5bc0de}.btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 2px rgba(91,192,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.btn-outline-info.active,.btn-outline-info:active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-success{color:#5cb85c;background-image:none;background-color:transparent;border-color:#5cb85c}.btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 2px rgba(92,184,92,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#5cb85c;background-color:transparent}.btn-outline-success.active,.btn-outline-success:active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-warning{color:#f0ad4e;background-image:none;background-color:transparent;border-color:#f0ad4e}.btn-outline-warning:hover{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 2px rgba(240,173,78,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#f0ad4e;background-color:transparent}.btn-outline-warning.active,.btn-outline-warning:active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-danger{color:#d9534f;background-image:none;background-color:transparent;border-color:#d9534f}.btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 2px rgba(217,83,79,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#d9534f;background-color:transparent}.btn-outline-danger.active,.btn-outline-danger:active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-link{font-weight:400;color:#0275d8;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link:disabled{background-color:transparent}.btn-link,.btn-link:active,.btn-link:focus{border-color:transparent}.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#014c8c;text-decoration:underline;background-color:transparent}.btn-link:disabled{color:#636c72}.btn-link:disabled:focus,.btn-link:disabled:hover{text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.show{opacity:1}.collapse{display:none}.collapse.show{display:block}tr.collapse.show{display:table-row}tbody.collapse.show{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.dropdown,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.3em;vertical-align:middle;content:\\\"\\\";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent}.dropdown-toggle:focus{outline:0}.dropup .dropdown-toggle::after{border-top:0;border-bottom:.3em solid}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#292b2c;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-divider{height:1px;margin:.5rem 0;overflow:hidden;background-color:#eceeef}.dropdown-item{display:block;width:100%;padding:3px 1.5rem;clear:both;font-weight:400;color:#292b2c;text-align:inherit;white-space:nowrap;background:0 0;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#1d1e1f;text-decoration:none;background-color:#f7f7f9}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0275d8}.dropdown-item.disabled,.dropdown-item:disabled{color:#636c72;cursor:not-allowed;background-color:transparent}.show>.dropdown-menu{display:block}.show>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#636c72;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.dropup .dropdown-menu{top:auto;bottom:100%;margin-bottom:.125rem}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:2}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn+.dropdown-toggle-split::after{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:1.125rem;padding-left:1.125rem}.btn-group-vertical{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.input-group .form-control{position:relative;z-index:2;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group .form-control:active,.input-group .form-control:focus,.input-group .form-control:hover{z-index:3}.input-group .form-control,.input-group-addon,.input-group-btn{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{white-space:nowrap;vertical-align:middle}.input-group-addon{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.25;color:#464a4c;text-align:center;background-color:#eceeef;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.input-group-addon.form-control-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-addon.form-control-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:not(:last-child),.input-group-addon:not(:last-child),.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn,.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group>.btn,.input-group-btn:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:not(:last-child){border-right:0}.input-group .form-control:not(:first-child),.input-group-addon:not(:first-child),.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group>.btn,.input-group-btn:not(:first-child)>.dropdown-toggle,.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn,.input-group-btn:not(:last-child)>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.form-control+.input-group-addon:not(:first-child){border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative;-webkit-box-flex:1;-ms-flex:1 1 0%;flex:1 1 0%}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:3}.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group{margin-right:-1px}.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group{z-index:2;margin-left:-1px}.input-group-btn:not(:first-child)>.btn-group:active,.input-group-btn:not(:first-child)>.btn-group:focus,.input-group-btn:not(:first-child)>.btn-group:hover,.input-group-btn:not(:first-child)>.btn:active,.input-group-btn:not(:first-child)>.btn:focus,.input-group-btn:not(:first-child)>.btn:hover{z-index:3}.custom-control{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;min-height:1.5rem;padding-left:1.5rem;margin-right:1rem;cursor:pointer}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-indicator{color:#fff;background-color:#0275d8}.custom-control-input:focus~.custom-control-indicator{box-shadow:0 0 0 1px #fff,0 0 0 3px #0275d8}.custom-control-input:active~.custom-control-indicator{color:#fff;background-color:#8fcafe}.custom-control-input:disabled~.custom-control-indicator{cursor:not-allowed;background-color:#eceeef}.custom-control-input:disabled~.custom-control-description{color:#636c72;cursor:not-allowed}.custom-control-indicator{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#ddd;background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-checkbox .custom-control-indicator{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-indicator{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\\\")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator{background-color:#0275d8;background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E\\\")}.custom-radio .custom-control-indicator{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-indicator{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\\\")}.custom-controls-stacked{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.custom-controls-stacked .custom-control{margin-bottom:.25rem}.custom-controls-stacked .custom-control+.custom-control{margin-left:0}.custom-select{display:inline-block;max-width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.25;color:#464a4c;vertical-align:middle;background:#fff url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\\\") no-repeat right .75rem center;background-size:8px 10px;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-moz-appearance:none;-webkit-appearance:none}.custom-select:focus{border-color:#5cb3fd;outline:0}.custom-select:focus::-ms-value{color:#464a4c;background-color:#fff}.custom-select:disabled{color:#636c72;cursor:not-allowed;background-color:#eceeef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-file{position:relative;display:inline-block;max-width:100%;height:2.5rem;margin-bottom:0;cursor:pointer}.custom-file-input{min-width:14rem;max-width:100%;height:2.5rem;margin:0;filter:alpha(opacity=0);opacity:0}.custom-file-control{position:absolute;top:0;right:0;left:0;z-index:5;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#464a4c;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.custom-file-control:lang(en)::after{content:\\\"Choose file...\\\"}.custom-file-control::before{position:absolute;top:-1px;right:-1px;bottom:-1px;z-index:6;display:block;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#464a4c;background-color:#eceeef;border:1px solid rgba(0,0,0,.15);border-radius:0 .25rem .25rem 0}.custom-file-control:lang(en)::before{content:\\\"Browse\\\"}.nav{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5em 1em}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#636c72;cursor:not-allowed}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-right-radius:.25rem;border-top-left-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#eceeef #eceeef #ddd}.nav-tabs .nav-link.disabled{color:#636c72;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#464a4c;background-color:#fff;border-color:#ddd #ddd #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-item.show .nav-link,.nav-pills .nav-link.active{color:#fff;cursor:default;background-color:#0275d8}.nav-fill .nav-item{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-webkit-box-flex:1;-ms-flex:1 1 100%;flex:1 1 100%;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:.5rem 1rem}.navbar-brand{display:inline-block;padding-top:.25rem;padding-bottom:.25rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-text{display:inline-block;padding-top:.425rem;padding-bottom:.425rem}.navbar-toggler{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;padding:.25rem .75rem;font-size:1.25rem;line-height:1;background:0 0;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:\\\"\\\";background:no-repeat center center;background-size:100% 100%}.navbar-toggler-left{position:absolute;left:1rem}.navbar-toggler-right{position:absolute;right:1rem}@media (max-width:575px){.navbar-toggleable .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable>.container{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-toggleable{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable>.container{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable .navbar-toggler{display:none}}@media (max-width:767px){.navbar-toggleable-sm .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-sm>.container{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-toggleable-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-sm>.container{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-sm .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-sm .navbar-toggler{display:none}}@media (max-width:991px){.navbar-toggleable-md .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-md>.container{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-toggleable-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-md>.container{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-md .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-md .navbar-toggler{display:none}}@media (max-width:1199px){.navbar-toggleable-lg .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-lg>.container{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-toggleable-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-lg>.container{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-lg .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-lg .navbar-toggler{display:none}}.navbar-toggleable-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-xl .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-xl>.container{padding-right:0;padding-left:0}.navbar-toggleable-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-xl>.container{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-xl .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-xl .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-toggler{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover,.navbar-light .navbar-toggler:focus,.navbar-light .navbar-toggler:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.open,.navbar-light .navbar-nav .open>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E\\\")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-toggler{color:#fff}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-toggler:focus,.navbar-inverse .navbar-toggler:hover{color:#fff}.navbar-inverse .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-inverse .navbar-nav .nav-link:focus,.navbar-inverse .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-inverse .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-inverse .navbar-nav .active>.nav-link,.navbar-inverse .navbar-nav .nav-link.active,.navbar-inverse .navbar-nav .nav-link.open,.navbar-inverse .navbar-nav .open>.nav-link{color:#fff}.navbar-inverse .navbar-toggler{border-color:rgba(255,255,255,.1)}.navbar-inverse .navbar-toggler-icon{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E\\\")}.navbar-inverse .navbar-text{color:rgba(255,255,255,.5)}.card{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card-block{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card>.list-group:first-child .list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:#f7f7f9;border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:#f7f7f9;border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-primary{background-color:#0275d8;border-color:#0275d8}.card-primary .card-footer,.card-primary .card-header{background-color:transparent}.card-success{background-color:#5cb85c;border-color:#5cb85c}.card-success .card-footer,.card-success .card-header{background-color:transparent}.card-info{background-color:#5bc0de;border-color:#5bc0de}.card-info .card-footer,.card-info .card-header{background-color:transparent}.card-warning{background-color:#f0ad4e;border-color:#f0ad4e}.card-warning .card-footer,.card-warning .card-header{background-color:transparent}.card-danger{background-color:#d9534f;border-color:#d9534f}.card-danger .card-footer,.card-danger .card-header{background-color:transparent}.card-outline-primary{background-color:transparent;border-color:#0275d8}.card-outline-secondary{background-color:transparent;border-color:#ccc}.card-outline-info{background-color:transparent;border-color:#5bc0de}.card-outline-success{background-color:transparent;border-color:#5cb85c}.card-outline-warning{background-color:transparent;border-color:#f0ad4e}.card-outline-danger{background-color:transparent;border-color:#d9534f}.card-inverse{color:rgba(255,255,255,.65)}.card-inverse .card-footer,.card-inverse .card-header{background-color:transparent;border-color:rgba(255,255,255,.2)}.card-inverse .card-blockquote,.card-inverse .card-footer,.card-inverse .card-header,.card-inverse .card-title{color:#fff}.card-inverse .card-blockquote .blockquote-footer,.card-inverse .card-link,.card-inverse .card-subtitle,.card-inverse .card-text{color:rgba(255,255,255,.65)}.card-inverse .card-link:focus,.card-inverse .card-link:hover{color:#fff}.card-blockquote{padding:0;margin-bottom:0;border-left:0}.card-img{border-radius:calc(.25rem - 1px)}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img-top{border-top-right-radius:calc(.25rem - 1px);border-top-left-radius:calc(.25rem - 1px)}.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}@media (min-width:576px){.card-deck{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap}.card-deck .card{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.card-deck .card:not(:first-child){margin-left:15px}.card-deck .card:not(:last-child){margin-right:15px}}@media (min-width:576px){.card-group{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap}.card-group .card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%}.card-group .card+.card{margin-left:0;border-left:0}.card-group .card:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.card-group .card:first-child .card-img-top{border-top-right-radius:0}.card-group .card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group .card:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.card-group .card:last-child .card-img-top{border-top-left-radius:0}.card-group .card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group .card:not(:first-child):not(:last-child){border-radius:0}.card-group .card:not(:first-child):not(:last-child) .card-img-bottom,.card-group .card:not(:first-child):not(:last-child) .card-img-top{border-radius:0}}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%;margin-bottom:.75rem}}.breadcrumb{padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eceeef;border-radius:.25rem}.breadcrumb::after{display:block;content:\\\"\\\";clear:both}.breadcrumb-item{float:left}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#636c72;content:\\\"/\\\"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#636c72}.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-item:first-child .page-link{margin-left:0;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{z-index:2;color:#fff;background-color:#0275d8;border-color:#0275d8}.page-item.disabled .page-link{color:#636c72;pointer-events:none;cursor:not-allowed;background-color:#fff;border-color:#ddd}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#0275d8;background-color:#fff;border:1px solid #ddd}.page-link:focus,.page-link:hover{color:#014c8c;text-decoration:none;background-color:#eceeef;border-color:#ddd}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-default{background-color:#636c72}.badge-default[href]:focus,.badge-default[href]:hover{background-color:#4b5257}.badge-primary{background-color:#0275d8}.badge-primary[href]:focus,.badge-primary[href]:hover{background-color:#025aa5}.badge-success{background-color:#5cb85c}.badge-success[href]:focus,.badge-success[href]:hover{background-color:#449d44}.badge-info{background-color:#5bc0de}.badge-info[href]:focus,.badge-info[href]:hover{background-color:#31b0d5}.badge-warning{background-color:#f0ad4e}.badge-warning[href]:focus,.badge-warning[href]:hover{background-color:#ec971f}.badge-danger{background-color:#d9534f}.badge-danger[href]:focus,.badge-danger[href]:hover{background-color:#c9302c}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eceeef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-hr{border-top-color:#d0d5d8}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible .close{position:relative;top:-.75rem;right:-1.25rem;padding:.75rem 1.25rem;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d0e9c6;color:#3c763d}.alert-success hr{border-top-color:#c1e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bcdff1;color:#31708f}.alert-info hr{border-top-color:#a6d5ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faf2cc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7ecb5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebcccc;color:#a94442}.alert-danger hr{border-top-color:#e4b9b9}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-ms-flexbox;display:flex;overflow:hidden;font-size:.75rem;line-height:1rem;text-align:center;background-color:#eceeef;border-radius:.25rem}.progress-bar{height:1rem;color:#fff;background-color:#0275d8}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-ms-flex:1 1 0%;flex:1 1 0%}.list-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#464a4c;text-align:inherit}.list-group-item-action .list-group-item-heading{color:#292b2c}.list-group-item-action:focus,.list-group-item-action:hover{color:#464a4c;text-decoration:none;background-color:#f7f7f9}.list-group-item-action:active{color:#292b2c;background-color:#eceeef}.list-group-item{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#636c72;cursor:not-allowed;background-color:#fff}.list-group-item.disabled .list-group-item-heading,.list-group-item:disabled .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item:disabled .list-group-item-text{color:#636c72}.list-group-item.active{z-index:2;color:#fff;background-color:#0275d8;border-color:#0275d8}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text{color:#daeeff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active{color:#fff;background-color:#a94442;border-color:#a94442}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:\\\"\\\"}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.75}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out, -webkit-transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:15px;border-bottom:1px solid #eceeef}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:15px}.modal-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:15px;border-top:1px solid #eceeef}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:30px auto}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:-apple-system,system-ui,BlinkMacSystemFont,\\\"Segoe UI\\\",Roboto,\\\"Helvetica Neue\\\",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip.bs-tether-element-attached-bottom,.tooltip.tooltip-top{padding:5px 0;margin-top:-3px}.tooltip.bs-tether-element-attached-bottom .tooltip-inner::before,.tooltip.tooltip-top .tooltip-inner::before{bottom:0;left:50%;margin-left:-5px;content:\\\"\\\";border-width:5px 5px 0;border-top-color:#000}.tooltip.bs-tether-element-attached-left,.tooltip.tooltip-right{padding:0 5px;margin-left:3px}.tooltip.bs-tether-element-attached-left .tooltip-inner::before,.tooltip.tooltip-right .tooltip-inner::before{top:50%;left:0;margin-top:-5px;content:\\\"\\\";border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.bs-tether-element-attached-top,.tooltip.tooltip-bottom{padding:5px 0;margin-top:3px}.tooltip.bs-tether-element-attached-top .tooltip-inner::before,.tooltip.tooltip-bottom .tooltip-inner::before{top:0;left:50%;margin-left:-5px;content:\\\"\\\";border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bs-tether-element-attached-right,.tooltip.tooltip-left{padding:0 5px;margin-left:-3px}.tooltip.bs-tether-element-attached-right .tooltip-inner::before,.tooltip.tooltip-left .tooltip-inner::before{top:50%;right:0;margin-top:-5px;content:\\\"\\\";border-width:5px 0 5px 5px;border-left-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.tooltip-inner::before{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;padding:1px;font-family:-apple-system,system-ui,BlinkMacSystemFont,\\\"Segoe UI\\\",Roboto,\\\"Helvetica Neue\\\",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover.bs-tether-element-attached-bottom,.popover.popover-top{margin-top:-10px}.popover.bs-tether-element-attached-bottom::after,.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::after,.popover.popover-top::before{left:50%;border-bottom-width:0}.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::before{bottom:-11px;margin-left:-11px;border-top-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-bottom::after,.popover.popover-top::after{bottom:-10px;margin-left:-10px;border-top-color:#fff}.popover.bs-tether-element-attached-left,.popover.popover-right{margin-left:10px}.popover.bs-tether-element-attached-left::after,.popover.bs-tether-element-attached-left::before,.popover.popover-right::after,.popover.popover-right::before{top:50%;border-left-width:0}.popover.bs-tether-element-attached-left::before,.popover.popover-right::before{left:-11px;margin-top:-11px;border-right-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-left::after,.popover.popover-right::after{left:-10px;margin-top:-10px;border-right-color:#fff}.popover.bs-tether-element-attached-top,.popover.popover-bottom{margin-top:10px}.popover.bs-tether-element-attached-top::after,.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::after,.popover.popover-bottom::before{left:50%;border-top-width:0}.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::before{top:-11px;margin-left:-11px;border-bottom-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-top::after,.popover.popover-bottom::after{top:-10px;margin-left:-10px;border-bottom-color:#f7f7f7}.popover.bs-tether-element-attached-top .popover-title::before,.popover.popover-bottom .popover-title::before{position:absolute;top:0;left:50%;display:block;width:20px;margin-left:-10px;content:\\\"\\\";border-bottom:1px solid #f7f7f7}.popover.bs-tether-element-attached-right,.popover.popover-left{margin-left:-10px}.popover.bs-tether-element-attached-right::after,.popover.bs-tether-element-attached-right::before,.popover.popover-left::after,.popover.popover-left::before{top:50%;border-right-width:0}.popover.bs-tether-element-attached-right::before,.popover.popover-left::before{right:-11px;margin-top:-11px;border-left-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-right::after,.popover.popover-left::after{right:-10px;margin-top:-10px;border-left-color:#fff}.popover-title{padding:8px 14px;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-right-radius:calc(.3rem - 1px);border-top-left-radius:calc(.3rem - 1px)}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover::after,.popover::before{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover::before{content:\\\"\\\";border-width:11px}.popover::after{content:\\\"\\\";border-width:10px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;width:100%}@media (-webkit-transform-3d){.carousel-item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out, -webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}}@supports ((-webkit-transform: translate3d(0,0,0)) or (transform: translate3d(0,0,0))){.carousel-item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out, -webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:-webkit-box;display:-ms-flexbox;display:flex}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}@media (-webkit-transform-3d){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@supports ((-webkit-transform: translate3d(0,0,0)) or (transform: translate3d(0,0,0))){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;background-size:100% 100%}.carousel-control-prev-icon{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M4 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\\\")}.carousel-control-next-icon{background-image:url(\\\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\\\")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:1;-ms-flex:1 0 auto;flex:1 0 auto;max-width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:\\\"\\\"}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:\\\"\\\"}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-faded{background-color:#f7f7f7}.bg-primary{background-color:#0275d8!important}a.bg-primary:focus,a.bg-primary:hover{background-color:#025aa5!important}.bg-success{background-color:#5cb85c!important}a.bg-success:focus,a.bg-success:hover{background-color:#449d44!important}.bg-info{background-color:#5bc0de!important}a.bg-info:focus,a.bg-info:hover{background-color:#31b0d5!important}.bg-warning{background-color:#f0ad4e!important}a.bg-warning:focus,a.bg-warning:hover{background-color:#ec971f!important}.bg-danger{background-color:#d9534f!important}a.bg-danger:focus,a.bg-danger:hover{background-color:#c9302c!important}.bg-inverse{background-color:#292b2c!important}a.bg-inverse:focus,a.bg-inverse:hover{background-color:#101112!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.rounded{border-radius:.25rem}.rounded-top{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.rounded-right{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.rounded-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-left{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-circle{border-radius:50%}.rounded-0{border-radius:0}.clearfix::after{display:block;content:\\\"\\\";clear:both}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.flex-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.flex-unordered{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.flex-sm-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.flex-sm-unordered{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-sm-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.flex-md-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.flex-md-unordered{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-md-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.flex-lg-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.flex-lg-unordered{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-lg-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.flex-xl-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.flex-xl-unordered{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-xl-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1030}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0 0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-right:0!important;margin-left:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:.25rem .25rem!important}.mt-1{margin-top:.25rem!important}.mr-1{margin-right:.25rem!important}.mb-1{margin-bottom:.25rem!important}.ml-1{margin-left:.25rem!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-2{margin:.5rem .5rem!important}.mt-2{margin-top:.5rem!important}.mr-2{margin-right:.5rem!important}.mb-2{margin-bottom:.5rem!important}.ml-2{margin-left:.5rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-3{margin:1rem 1rem!important}.mt-3{margin-top:1rem!important}.mr-3{margin-right:1rem!important}.mb-3{margin-bottom:1rem!important}.ml-3{margin-left:1rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-4{margin:1.5rem 1.5rem!important}.mt-4{margin-top:1.5rem!important}.mr-4{margin-right:1.5rem!important}.mb-4{margin-bottom:1.5rem!important}.ml-4{margin-left:1.5rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-5{margin:3rem 3rem!important}.mt-5{margin-top:3rem!important}.mr-5{margin-right:3rem!important}.mb-5{margin-bottom:3rem!important}.ml-5{margin-left:3rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-0{padding:0 0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-right:0!important;padding-left:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:.25rem .25rem!important}.pt-1{padding-top:.25rem!important}.pr-1{padding-right:.25rem!important}.pb-1{padding-bottom:.25rem!important}.pl-1{padding-left:.25rem!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-2{padding:.5rem .5rem!important}.pt-2{padding-top:.5rem!important}.pr-2{padding-right:.5rem!important}.pb-2{padding-bottom:.5rem!important}.pl-2{padding-left:.5rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-3{padding:1rem 1rem!important}.pt-3{padding-top:1rem!important}.pr-3{padding-right:1rem!important}.pb-3{padding-bottom:1rem!important}.pl-3{padding-left:1rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-4{padding:1.5rem 1.5rem!important}.pt-4{padding-top:1.5rem!important}.pr-4{padding-right:1.5rem!important}.pb-4{padding-bottom:1.5rem!important}.pl-4{padding-left:1.5rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-5{padding:3rem 3rem!important}.pt-5{padding-top:3rem!important}.pr-5{padding-right:3rem!important}.pb-5{padding-bottom:3rem!important}.pl-5{padding-left:3rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-auto{margin:auto!important}.mt-auto{margin-top:auto!important}.mr-auto{margin-right:auto!important}.mb-auto{margin-bottom:auto!important}.ml-auto{margin-left:auto!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}@media (min-width:576px){.m-sm-0{margin:0 0!important}.mt-sm-0{margin-top:0!important}.mr-sm-0{margin-right:0!important}.mb-sm-0{margin-bottom:0!important}.ml-sm-0{margin-left:0!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.m-sm-1{margin:.25rem .25rem!important}.mt-sm-1{margin-top:.25rem!important}.mr-sm-1{margin-right:.25rem!important}.mb-sm-1{margin-bottom:.25rem!important}.ml-sm-1{margin-left:.25rem!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-sm-2{margin:.5rem .5rem!important}.mt-sm-2{margin-top:.5rem!important}.mr-sm-2{margin-right:.5rem!important}.mb-sm-2{margin-bottom:.5rem!important}.ml-sm-2{margin-left:.5rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-sm-3{margin:1rem 1rem!important}.mt-sm-3{margin-top:1rem!important}.mr-sm-3{margin-right:1rem!important}.mb-sm-3{margin-bottom:1rem!important}.ml-sm-3{margin-left:1rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-sm-4{margin:1.5rem 1.5rem!important}.mt-sm-4{margin-top:1.5rem!important}.mr-sm-4{margin-right:1.5rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.ml-sm-4{margin-left:1.5rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-sm-5{margin:3rem 3rem!important}.mt-sm-5{margin-top:3rem!important}.mr-sm-5{margin-right:3rem!important}.mb-sm-5{margin-bottom:3rem!important}.ml-sm-5{margin-left:3rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-sm-0{padding:0 0!important}.pt-sm-0{padding-top:0!important}.pr-sm-0{padding-right:0!important}.pb-sm-0{padding-bottom:0!important}.pl-sm-0{padding-left:0!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.p-sm-1{padding:.25rem .25rem!important}.pt-sm-1{padding-top:.25rem!important}.pr-sm-1{padding-right:.25rem!important}.pb-sm-1{padding-bottom:.25rem!important}.pl-sm-1{padding-left:.25rem!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-sm-2{padding:.5rem .5rem!important}.pt-sm-2{padding-top:.5rem!important}.pr-sm-2{padding-right:.5rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pl-sm-2{padding-left:.5rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-sm-3{padding:1rem 1rem!important}.pt-sm-3{padding-top:1rem!important}.pr-sm-3{padding-right:1rem!important}.pb-sm-3{padding-bottom:1rem!important}.pl-sm-3{padding-left:1rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-sm-4{padding:1.5rem 1.5rem!important}.pt-sm-4{padding-top:1.5rem!important}.pr-sm-4{padding-right:1.5rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pl-sm-4{padding-left:1.5rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-sm-5{padding:3rem 3rem!important}.pt-sm-5{padding-top:3rem!important}.pr-sm-5{padding-right:3rem!important}.pb-sm-5{padding-bottom:3rem!important}.pl-sm-5{padding-left:3rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto{margin-top:auto!important}.mr-sm-auto{margin-right:auto!important}.mb-sm-auto{margin-bottom:auto!important}.ml-sm-auto{margin-left:auto!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:768px){.m-md-0{margin:0 0!important}.mt-md-0{margin-top:0!important}.mr-md-0{margin-right:0!important}.mb-md-0{margin-bottom:0!important}.ml-md-0{margin-left:0!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.m-md-1{margin:.25rem .25rem!important}.mt-md-1{margin-top:.25rem!important}.mr-md-1{margin-right:.25rem!important}.mb-md-1{margin-bottom:.25rem!important}.ml-md-1{margin-left:.25rem!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-md-2{margin:.5rem .5rem!important}.mt-md-2{margin-top:.5rem!important}.mr-md-2{margin-right:.5rem!important}.mb-md-2{margin-bottom:.5rem!important}.ml-md-2{margin-left:.5rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-md-3{margin:1rem 1rem!important}.mt-md-3{margin-top:1rem!important}.mr-md-3{margin-right:1rem!important}.mb-md-3{margin-bottom:1rem!important}.ml-md-3{margin-left:1rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-md-4{margin:1.5rem 1.5rem!important}.mt-md-4{margin-top:1.5rem!important}.mr-md-4{margin-right:1.5rem!important}.mb-md-4{margin-bottom:1.5rem!important}.ml-md-4{margin-left:1.5rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-md-5{margin:3rem 3rem!important}.mt-md-5{margin-top:3rem!important}.mr-md-5{margin-right:3rem!important}.mb-md-5{margin-bottom:3rem!important}.ml-md-5{margin-left:3rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-md-0{padding:0 0!important}.pt-md-0{padding-top:0!important}.pr-md-0{padding-right:0!important}.pb-md-0{padding-bottom:0!important}.pl-md-0{padding-left:0!important}.px-md-0{padding-right:0!important;padding-left:0!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.p-md-1{padding:.25rem .25rem!important}.pt-md-1{padding-top:.25rem!important}.pr-md-1{padding-right:.25rem!important}.pb-md-1{padding-bottom:.25rem!important}.pl-md-1{padding-left:.25rem!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-md-2{padding:.5rem .5rem!important}.pt-md-2{padding-top:.5rem!important}.pr-md-2{padding-right:.5rem!important}.pb-md-2{padding-bottom:.5rem!important}.pl-md-2{padding-left:.5rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-md-3{padding:1rem 1rem!important}.pt-md-3{padding-top:1rem!important}.pr-md-3{padding-right:1rem!important}.pb-md-3{padding-bottom:1rem!important}.pl-md-3{padding-left:1rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-md-4{padding:1.5rem 1.5rem!important}.pt-md-4{padding-top:1.5rem!important}.pr-md-4{padding-right:1.5rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pl-md-4{padding-left:1.5rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-md-5{padding:3rem 3rem!important}.pt-md-5{padding-top:3rem!important}.pr-md-5{padding-right:3rem!important}.pb-md-5{padding-bottom:3rem!important}.pl-md-5{padding-left:3rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto{margin-top:auto!important}.mr-md-auto{margin-right:auto!important}.mb-md-auto{margin-bottom:auto!important}.ml-md-auto{margin-left:auto!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:992px){.m-lg-0{margin:0 0!important}.mt-lg-0{margin-top:0!important}.mr-lg-0{margin-right:0!important}.mb-lg-0{margin-bottom:0!important}.ml-lg-0{margin-left:0!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.m-lg-1{margin:.25rem .25rem!important}.mt-lg-1{margin-top:.25rem!important}.mr-lg-1{margin-right:.25rem!important}.mb-lg-1{margin-bottom:.25rem!important}.ml-lg-1{margin-left:.25rem!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-lg-2{margin:.5rem .5rem!important}.mt-lg-2{margin-top:.5rem!important}.mr-lg-2{margin-right:.5rem!important}.mb-lg-2{margin-bottom:.5rem!important}.ml-lg-2{margin-left:.5rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-lg-3{margin:1rem 1rem!important}.mt-lg-3{margin-top:1rem!important}.mr-lg-3{margin-right:1rem!important}.mb-lg-3{margin-bottom:1rem!important}.ml-lg-3{margin-left:1rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-lg-4{margin:1.5rem 1.5rem!important}.mt-lg-4{margin-top:1.5rem!important}.mr-lg-4{margin-right:1.5rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.ml-lg-4{margin-left:1.5rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-lg-5{margin:3rem 3rem!important}.mt-lg-5{margin-top:3rem!important}.mr-lg-5{margin-right:3rem!important}.mb-lg-5{margin-bottom:3rem!important}.ml-lg-5{margin-left:3rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-lg-0{padding:0 0!important}.pt-lg-0{padding-top:0!important}.pr-lg-0{padding-right:0!important}.pb-lg-0{padding-bottom:0!important}.pl-lg-0{padding-left:0!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.p-lg-1{padding:.25rem .25rem!important}.pt-lg-1{padding-top:.25rem!important}.pr-lg-1{padding-right:.25rem!important}.pb-lg-1{padding-bottom:.25rem!important}.pl-lg-1{padding-left:.25rem!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-lg-2{padding:.5rem .5rem!important}.pt-lg-2{padding-top:.5rem!important}.pr-lg-2{padding-right:.5rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pl-lg-2{padding-left:.5rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-lg-3{padding:1rem 1rem!important}.pt-lg-3{padding-top:1rem!important}.pr-lg-3{padding-right:1rem!important}.pb-lg-3{padding-bottom:1rem!important}.pl-lg-3{padding-left:1rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-lg-4{padding:1.5rem 1.5rem!important}.pt-lg-4{padding-top:1.5rem!important}.pr-lg-4{padding-right:1.5rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pl-lg-4{padding-left:1.5rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-lg-5{padding:3rem 3rem!important}.pt-lg-5{padding-top:3rem!important}.pr-lg-5{padding-right:3rem!important}.pb-lg-5{padding-bottom:3rem!important}.pl-lg-5{padding-left:3rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto{margin-top:auto!important}.mr-lg-auto{margin-right:auto!important}.mb-lg-auto{margin-bottom:auto!important}.ml-lg-auto{margin-left:auto!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0 0!important}.mt-xl-0{margin-top:0!important}.mr-xl-0{margin-right:0!important}.mb-xl-0{margin-bottom:0!important}.ml-xl-0{margin-left:0!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.m-xl-1{margin:.25rem .25rem!important}.mt-xl-1{margin-top:.25rem!important}.mr-xl-1{margin-right:.25rem!important}.mb-xl-1{margin-bottom:.25rem!important}.ml-xl-1{margin-left:.25rem!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-xl-2{margin:.5rem .5rem!important}.mt-xl-2{margin-top:.5rem!important}.mr-xl-2{margin-right:.5rem!important}.mb-xl-2{margin-bottom:.5rem!important}.ml-xl-2{margin-left:.5rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-xl-3{margin:1rem 1rem!important}.mt-xl-3{margin-top:1rem!important}.mr-xl-3{margin-right:1rem!important}.mb-xl-3{margin-bottom:1rem!important}.ml-xl-3{margin-left:1rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-xl-4{margin:1.5rem 1.5rem!important}.mt-xl-4{margin-top:1.5rem!important}.mr-xl-4{margin-right:1.5rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.ml-xl-4{margin-left:1.5rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-xl-5{margin:3rem 3rem!important}.mt-xl-5{margin-top:3rem!important}.mr-xl-5{margin-right:3rem!important}.mb-xl-5{margin-bottom:3rem!important}.ml-xl-5{margin-left:3rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-xl-0{padding:0 0!important}.pt-xl-0{padding-top:0!important}.pr-xl-0{padding-right:0!important}.pb-xl-0{padding-bottom:0!important}.pl-xl-0{padding-left:0!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.p-xl-1{padding:.25rem .25rem!important}.pt-xl-1{padding-top:.25rem!important}.pr-xl-1{padding-right:.25rem!important}.pb-xl-1{padding-bottom:.25rem!important}.pl-xl-1{padding-left:.25rem!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-xl-2{padding:.5rem .5rem!important}.pt-xl-2{padding-top:.5rem!important}.pr-xl-2{padding-right:.5rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pl-xl-2{padding-left:.5rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-xl-3{padding:1rem 1rem!important}.pt-xl-3{padding-top:1rem!important}.pr-xl-3{padding-right:1rem!important}.pb-xl-3{padding-bottom:1rem!important}.pl-xl-3{padding-left:1rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-xl-4{padding:1.5rem 1.5rem!important}.pt-xl-4{padding-top:1.5rem!important}.pr-xl-4{padding-right:1.5rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pl-xl-4{padding-left:1.5rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-xl-5{padding:3rem 3rem!important}.pt-xl-5{padding-top:3rem!important}.pr-xl-5{padding-right:3rem!important}.pb-xl-5{padding-bottom:3rem!important}.pl-xl-5{padding-left:3rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto{margin-top:auto!important}.mr-xl-auto{margin-right:auto!important}.mb-xl-auto{margin-bottom:auto!important}.ml-xl-auto{margin-left:auto!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-normal{font-weight:400}.font-weight-bold{font-weight:700}.font-italic{font-style:italic}.text-white{color:#fff!important}.text-muted{color:#636c72!important}a.text-muted:focus,a.text-muted:hover{color:#4b5257!important}.text-primary{color:#0275d8!important}a.text-primary:focus,a.text-primary:hover{color:#025aa5!important}.text-success{color:#5cb85c!important}a.text-success:focus,a.text-success:hover{color:#449d44!important}.text-info{color:#5bc0de!important}a.text-info:focus,a.text-info:hover{color:#31b0d5!important}.text-warning{color:#f0ad4e!important}a.text-warning:focus,a.text-warning:hover{color:#ec971f!important}.text-danger{color:#d9534f!important}a.text-danger:focus,a.text-danger:hover{color:#c9302c!important}.text-gray-dark{color:#292b2c!important}a.text-gray-dark:focus,a.text-gray-dark:hover{color:#101112!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.invisible{visibility:hidden!important}.hidden-xs-up{display:none!important}@media (max-width:575px){.hidden-xs-down{display:none!important}}@media (min-width:576px){.hidden-sm-up{display:none!important}}@media (max-width:767px){.hidden-sm-down{display:none!important}}@media (min-width:768px){.hidden-md-up{display:none!important}}@media (max-width:991px){.hidden-md-down{display:none!important}}@media (min-width:992px){.hidden-lg-up{display:none!important}}@media (max-width:1199px){.hidden-lg-down{display:none!important}}@media (min-width:1200px){.hidden-xl-up{display:none!important}}.hidden-xl-down{display:none!important}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}/*# sourceMappingURL=bootstrap.min.css.map */\", \"\"]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/css-loader?{\"sourceMap\":false,\"importLoaders\":1}!./~/postcss-loader!./~/bootstrap/dist/css/bootstrap.min.css\n// module id = 142\n// module chunks = 2","exports = module.exports = require(\"../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \"/* You can add global styles to this file, and also import other style files */\\r\\n\", \"\"]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/css-loader?{\"sourceMap\":false,\"importLoaders\":1}!./~/postcss-loader!./src/styles.css\n// module id = 143\n// module chunks = 2","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\nvar stylesInDom = {},\n\tmemoize = function(fn) {\n\t\tvar memo;\n\t\treturn function () {\n\t\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\t\treturn memo;\n\t\t};\n\t},\n\tisOldIE = memoize(function() {\n\t\treturn /msie [6-9]\\b/.test(self.navigator.userAgent.toLowerCase());\n\t}),\n\tgetHeadElement = memoize(function () {\n\t\treturn document.head || document.getElementsByTagName(\"head\")[0];\n\t}),\n\tsingletonElement = null,\n\tsingletonCounter = 0,\n\tstyleElementsInsertedAtTop = [];\n\nmodule.exports = function(list, options) {\n\tif(typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif(typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of