diff --git a/algorithms/README.md b/algorithms/README.md index 3401b6d935..31cb8076d9 100644 --- a/algorithms/README.md +++ b/algorithms/README.md @@ -16,3 +16,4 @@ - [Introduction to Minimax Algorithm](http://www.baeldung.com/java-minimax-algorithm) - [How to Calculate Levenshtein Distance in Java?](http://www.baeldung.com/java-levenshtein-distance) - [How to Find the Kth Largest Element in Java](http://www.baeldung.com/java-kth-largest-element) +- [Multi-Swarm Optimization Algorithm in Java](http://www.baeldung.com/java-multi-swarm-algorithm) diff --git a/algorithms/pom.xml b/algorithms/pom.xml index 2eb8cd42b6..8751cf45c0 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -9,6 +9,7 @@ 1.5.0 1.16.12 3.6.1 + 1.0.1 @@ -39,6 +40,11 @@ jgrapht-core 1.0.1 + + pl.allegro.finance + tradukisto + ${tradukisto.version} + org.assertj assertj-core @@ -46,7 +52,6 @@ test - @@ -77,4 +82,4 @@ - + \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java b/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java new file mode 100644 index 0000000000..0fe2960f96 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java @@ -0,0 +1,75 @@ +package com.baeldung.algorithms.numberwordconverter; + +import java.math.BigDecimal; + +import pl.allegro.finance.tradukisto.MoneyConverters; + +public class NumberWordConverter { + + public static final String INVALID_INPUT_GIVEN = "Invalid input given"; + + public static final String[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; + + public static final String[] tens = { + "", // 0 + "", // 1 + "twenty", // 2 + "thirty", // 3 + "forty", // 4 + "fifty", // 5 + "sixty", // 6 + "seventy", // 7 + "eighty", // 8 + "ninety" // 9 + }; + + public static String getMoneyIntoWords(String input) { + MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE; + return converter.asWords(new BigDecimal(input)); + } + + public static String getMoneyIntoWords(final double money) { + long dollar = (long) money; + long cents = Math.round((money - dollar) * 100); + if (money == 0D) { + return ""; + } + if (money < 0) { + return INVALID_INPUT_GIVEN; + } + String dollarPart = ""; + if (dollar > 0) { + dollarPart = convert(dollar) + " dollar" + (dollar == 1 ? "" : "s"); + } + String centsPart = ""; + if (cents > 0) { + if (dollarPart.length() > 0) { + centsPart = " and "; + } + centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s"); + } + return dollarPart + centsPart; + } + + private static String convert(final long n) { + if (n < 0) { + return INVALID_INPUT_GIVEN; + } + if (n < 20) { + return ones[(int) n]; + } + if (n < 100) { + return tens[(int) n / 10] + ((n % 10 != 0) ? " " : "") + ones[(int) n % 10]; + } + if (n < 1000) { + return ones[(int) n / 100] + " hundred" + ((n % 100 != 0) ? " " : "") + convert(n % 100); + } + if (n < 1_000_000) { + return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "") + convert(n % 1000); + } + if (n < 1_000_000_000) { + return convert(n / 1_000_000) + " million" + ((n % 1_000_000 != 0) ? " " : "") + convert(n % 1_000_000); + } + return convert(n / 1_000_000_000) + " billion" + ((n % 1_000_000_000 != 0) ? " " : "") + convert(n % 1_000_000_000); + } +} \ No newline at end of file diff --git a/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java b/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java new file mode 100644 index 0000000000..a4a169f158 --- /dev/null +++ b/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java @@ -0,0 +1,84 @@ +package com.baeldung.algorithms.moneywords; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.algorithms.numberwordconverter.NumberWordConverter; + +public class NumberWordConverterTest { + + @Test + public void whenMoneyNegative_thenReturnInvalidInput() { + assertEquals(NumberWordConverter.INVALID_INPUT_GIVEN, NumberWordConverter.getMoneyIntoWords(-13)); + } + + @Test + public void whenZeroDollarsGiven_thenReturnEmptyString() { + assertEquals("", NumberWordConverter.getMoneyIntoWords(0)); + } + + @Test + public void whenOnlyDollarsGiven_thenReturnWords() { + assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1)); + } + + @Test + public void whenOnlyCentsGiven_thenReturnWords() { + assertEquals("sixty cents", NumberWordConverter.getMoneyIntoWords(0.6)); + } + + @Test + public void whenAlmostAMillioDollarsGiven_thenReturnWords() { + String expectedResult = "nine hundred ninety nine thousand nine hundred ninety nine dollars"; + assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(999_999)); + } + + @Test + public void whenThirtyMillionDollarsGiven_thenReturnWords() { + String expectedResult = "thirty three million three hundred forty eight thousand nine hundred seventy eight dollars"; + assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(33_348_978)); + } + + @Test + public void whenTwoBillionDollarsGiven_thenReturnWords() { + String expectedResult = "two billion one hundred thirty three million two hundred forty seven thousand eight hundred ten dollars"; + assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(2_133_247_810)); + } + + @Test + public void whenGivenDollarsAndCents_thenReturnWords() { + String expectedResult = "nine hundred twenty four dollars and sixty cents"; + assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(924.6)); + } + + @Test + public void whenOneDollarAndNoCents_thenReturnDollarSingular() { + assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1)); + } + + @Test + public void whenNoDollarsAndOneCent_thenReturnCentSingular() { + assertEquals("one cent", NumberWordConverter.getMoneyIntoWords(0.01)); + } + + @Test + public void whenNoDollarsAndTwoCents_thenReturnCentsPlural() { + assertEquals("two cents", NumberWordConverter.getMoneyIntoWords(0.02)); + } + + @Test + public void whenNoDollarsAndNinetyNineCents_thenReturnWords() { + assertEquals("ninety nine cents", NumberWordConverter.getMoneyIntoWords(0.99)); + } + + @Test + public void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() { + assertEquals("ninety six cents", NumberWordConverter.getMoneyIntoWords(0.959)); + } + + @Test + public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() { + assertEquals("three hundred ten £ 00/100", NumberWordConverter.getMoneyIntoWords("310")); + } +} diff --git a/apache-curator/pom.xml b/apache-curator/pom.xml index 36c3949b1a..35549861c8 100644 --- a/apache-curator/pom.xml +++ b/apache-curator/pom.xml @@ -18,6 +18,7 @@ 3.6.1 + 1.7.0 @@ -64,5 +65,12 @@ ${assertj.version} test + + + com.jayway.awaitility + awaitility + ${avaitility.version} + test + diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java index 0475f9c237..d02ef8131d 100644 --- a/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java +++ b/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java @@ -1,5 +1,6 @@ package com.baeldung.apache.curator.configuration; +import static com.jayway.awaitility.Awaitility.await; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; @@ -26,30 +27,27 @@ public class ConfigurationManagementManualTest extends BaseTest { String expected = "my_value"; // Create key nodes structure - client - .create() - .forPath(key); + client.create() + .forPath(key); // Set data value for our key - async - .setData() - .forPath(key, expected.getBytes()); + async.setData() + .forPath(key, expected.getBytes()); // Get data value AtomicBoolean isEquals = new AtomicBoolean(); - async - .getData() - .forPath(key) - .thenAccept(data -> isEquals.set(new String(data).equals(expected))); + async.getData() + .forPath(key) + .thenAccept( + data -> isEquals.set(new String(data).equals(expected))); - Thread.sleep(1000); - - assertThat(isEquals.get()).isTrue(); + await().until(() -> assertThat(isEquals.get()).isTrue()); } } @Test - public void givenPath_whenWatchAKeyAndStoreAValue_thenWatcherIsTriggered() throws Exception { + public void givenPath_whenWatchAKeyAndStoreAValue_thenWatcherIsTriggered() + throws Exception { try (CuratorFramework client = newClient()) { client.start(); AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); @@ -57,42 +55,35 @@ public class ConfigurationManagementManualTest extends BaseTest { String expected = "my_value"; // Create key structure - async - .create() - .forPath(key); + async.create() + .forPath(key); List changes = new ArrayList<>(); // Watch data value - async - .watched() - .getData() - .forPath(key) - .event() - .thenAccept(watchedEvent -> { - try { - changes.add(new String(client - .getData() - .forPath(watchedEvent.getPath()))); - } catch (Exception e) { - // fail ... - } - }); + async.watched() + .getData() + .forPath(key) + .event() + .thenAccept(watchedEvent -> { + try { + changes.add(new String(client.getData() + .forPath(watchedEvent.getPath()))); + } catch (Exception e) { + // fail ... + } + }); // Set data value for our key - async - .setData() - .forPath(key, expected.getBytes()); + async.setData() + .forPath(key, expected.getBytes()); - Thread.sleep(1000); - - assertThat(changes.size() > 0).isTrue(); + await().until(() -> assertThat(changes.size() > 0).isTrue()); } } private String getKey() { - return String.format(KEY_FORMAT, UUID - .randomUUID() - .toString()); + return String.format(KEY_FORMAT, UUID.randomUUID() + .toString()); } } diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java index 931a977900..61fa1c7c2c 100644 --- a/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java +++ b/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java @@ -1,5 +1,6 @@ package com.baeldung.apache.curator.connection; +import static com.jayway.awaitility.Awaitility.await; import static org.assertj.core.api.Assertions.assertThat; import java.util.concurrent.atomic.AtomicBoolean; @@ -14,56 +15,65 @@ import org.junit.Test; public class ConnectionManagementManualTest { @Test - public void givenRunningZookeeper_whenOpenConnection_thenClientIsOpened() throws Exception { + public void givenRunningZookeeper_whenOpenConnection_thenClientIsOpened() + throws Exception { int sleepMsBetweenRetries = 100; int maxRetries = 3; - RetryPolicy retryPolicy = new RetryNTimes(maxRetries, sleepMsBetweenRetries); + RetryPolicy retryPolicy = new RetryNTimes(maxRetries, + sleepMsBetweenRetries); - try (CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy)) { + try (CuratorFramework client = CuratorFrameworkFactory + .newClient("127.0.0.1:2181", retryPolicy)) { client.start(); - assertThat(client - .checkExists() - .forPath("/")).isNotNull(); + + assertThat(client.checkExists() + .forPath("/")).isNotNull(); } } @Test - public void givenRunningZookeeper_whenOpenConnectionUsingAsyncNotBlocking_thenClientIsOpened() throws InterruptedException { + public void givenRunningZookeeper_whenOpenConnectionUsingAsyncNotBlocking_thenClientIsOpened() + throws InterruptedException { int sleepMsBetweenRetries = 100; int maxRetries = 3; - RetryPolicy retryPolicy = new RetryNTimes(maxRetries, sleepMsBetweenRetries); + RetryPolicy retryPolicy = new RetryNTimes(maxRetries, + sleepMsBetweenRetries); - try (CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy)) { + try (CuratorFramework client = CuratorFrameworkFactory + .newClient("127.0.0.1:2181", retryPolicy)) { client.start(); AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); AtomicBoolean exists = new AtomicBoolean(false); - async - .checkExists() - .forPath("/") - .thenAcceptAsync(s -> exists.set(s != null)); - Thread.sleep(100); - assertThat(exists.get()).isTrue(); + + async.checkExists() + .forPath("/") + .thenAcceptAsync(s -> exists.set(s != null)); + + await().until(() -> assertThat(exists.get()).isTrue()); } } @Test - public void givenRunningZookeeper_whenOpenConnectionUsingAsyncBlocking_thenClientIsOpened() throws InterruptedException { + public void givenRunningZookeeper_whenOpenConnectionUsingAsyncBlocking_thenClientIsOpened() + throws InterruptedException { int sleepMsBetweenRetries = 100; int maxRetries = 3; - RetryPolicy retryPolicy = new RetryNTimes(maxRetries, sleepMsBetweenRetries); + RetryPolicy retryPolicy = new RetryNTimes(maxRetries, + sleepMsBetweenRetries); - try (CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy)) { + try (CuratorFramework client = CuratorFrameworkFactory + .newClient("127.0.0.1:2181", retryPolicy)) { client.start(); AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); AtomicBoolean exists = new AtomicBoolean(false); - async - .checkExists() - .forPath("/") - .thenAccept(s -> exists.set(s != null)); - Thread.sleep(100); - assertThat(exists.get()).isTrue(); + + async.checkExists() + .forPath("/") + .thenAccept(s -> exists.set(s != null)); + + await().until(() -> assertThat(exists.get()).isTrue()); } } } diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java index 9d00c0a4c2..4400c1d1aa 100644 --- a/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java +++ b/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java @@ -16,31 +16,33 @@ import com.baeldung.apache.curator.BaseTest; public class ModelTypedExamplesManualTest extends BaseTest { @Test - public void givenPath_whenStoreAModel_thenNodesAreCreated() throws InterruptedException { + public void givenPath_whenStoreAModel_thenNodesAreCreated() + throws InterruptedException { ModelSpec mySpec = ModelSpec - .builder(ZPath.parseWithIds("/config/dev"), JacksonModelSerializer.build(HostConfig.class)) - .build(); + .builder(ZPath.parseWithIds("/config/dev"), + JacksonModelSerializer.build(HostConfig.class)) + .build(); try (CuratorFramework client = newClient()) { client.start(); AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); - ModeledFramework modeledClient = ModeledFramework.wrap(async, mySpec); + ModeledFramework modeledClient = ModeledFramework + .wrap(async, mySpec); modeledClient.set(new HostConfig("host-name", 8080)); - modeledClient - .read() - .whenComplete((value, e) -> { - if (e != null) { - fail("Cannot read host config", e); - } else { - assertThat(value).isNotNull(); - assertThat(value.getHostname()).isEqualTo("host-name"); - assertThat(value.getPort()).isEqualTo(8080); - } + modeledClient.read() + .whenComplete((value, e) -> { + if (e != null) { + fail("Cannot read host config", e); + } else { + assertThat(value).isNotNull(); + assertThat(value.getHostname()).isEqualTo("host-name"); + assertThat(value.getPort()).isEqualTo(8080); + } - }); + }); } } diff --git a/core-java/src/main/java/com/baeldung/array/Find2ndLargestInArray.java b/core-java/src/main/java/com/baeldung/array/Find2ndLargestInArray.java new file mode 100644 index 0000000000..d424bd429f --- /dev/null +++ b/core-java/src/main/java/com/baeldung/array/Find2ndLargestInArray.java @@ -0,0 +1,20 @@ +package com.baeldung.array; + +public class Find2ndLargestInArray { + + public static int find2ndLargestElement(int[] array) { + int maxElement = array[0]; + int secondLargestElement = -1; + + for (int index = 0; index < array.length; index++) { + if (maxElement <= array[index]) { + secondLargestElement = maxElement; + maxElement = array[index]; + } else if (secondLargestElement < array[index]) { + secondLargestElement = array[index]; + } + } + return secondLargestElement; + } + +} diff --git a/core-java/src/main/java/com/baeldung/array/FindElementInArray.java b/core-java/src/main/java/com/baeldung/array/FindElementInArray.java new file mode 100644 index 0000000000..6da889fe91 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/array/FindElementInArray.java @@ -0,0 +1,22 @@ +package com.baeldung.array; + +import java.util.Arrays; + +public class FindElementInArray { + + public static boolean findGivenElementInArrayWithoutUsingStream(int[] array, int element) { + boolean actualResult = false; + + for (int index = 0; index < array.length; index++) { + if (element == array[index]) { + actualResult = true; + break; + } + } + return actualResult; + } + + public static boolean findGivenElementInArrayUsingStream(int[] array, int element) { + return Arrays.stream(array).filter(x -> element == x).findFirst().isPresent(); + } +} diff --git a/core-java/src/main/java/com/baeldung/array/SumAndAverageInArray.java b/core-java/src/main/java/com/baeldung/array/SumAndAverageInArray.java new file mode 100644 index 0000000000..e7d7172fdb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/array/SumAndAverageInArray.java @@ -0,0 +1,27 @@ +package com.baeldung.array; + +import java.util.Arrays; + +public class SumAndAverageInArray { + + public static int findSumWithoutUsingStream(int[] array) { + int sum = 0; + for (int index = 0; index < array.length; index++) { + sum += array[index]; + } + return sum; + } + + public static int findSumUsingStream(int[] array) { + return Arrays.stream(array).sum(); + } + + public static double findAverageWithoutUsingStream(int[] array) { + int sum = findSumWithoutUsingStream(array); + return (double) sum / array.length; + } + + public static double findAverageUsingStream(int[] array) { + return Arrays.stream(array).average().getAsDouble(); + } +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java deleted file mode 100644 index 552a7ff6d9..0000000000 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.designpatterns.chainofresponsibility; - -public interface AuthenticationProvider { - -} diff --git a/core-java/src/test/java/com/baeldung/array/Find2ndLargestInArrayTest.java b/core-java/src/test/java/com/baeldung/array/Find2ndLargestInArrayTest.java new file mode 100644 index 0000000000..ec916af092 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/array/Find2ndLargestInArrayTest.java @@ -0,0 +1,16 @@ +package com.baeldung.array; + +import org.junit.Assert; +import org.junit.Test; + +public class Find2ndLargestInArrayTest { + @Test + public void givenAnIntArray_thenFind2ndLargestElement() { + int[] array = { 1, 3, 24, 16, 87, 20 }; + int expected2ndLargest = 24; + + int actualSecondLargestElement = Find2ndLargestInArray.find2ndLargestElement(array); + + Assert.assertEquals(expected2ndLargest, actualSecondLargestElement); + } +} diff --git a/core-java/src/test/java/com/baeldung/array/FindElementInArrayTest.java b/core-java/src/test/java/com/baeldung/array/FindElementInArrayTest.java new file mode 100644 index 0000000000..ba9188fa7b --- /dev/null +++ b/core-java/src/test/java/com/baeldung/array/FindElementInArrayTest.java @@ -0,0 +1,35 @@ +package com.baeldung.array; + +import org.junit.Assert; +import org.junit.Test; + +public class FindElementInArrayTest { + @Test + public void givenAnIntArray_whenNotUsingStream_thenFindAnElement() { + int[] array = { 1, 3, 4, 8, 19, 20 }; + int element = 19; + boolean expectedResult = true; + boolean actualResult = FindElementInArray.findGivenElementInArrayWithoutUsingStream(array, element); + Assert.assertEquals(expectedResult, actualResult); + + element = 78; + expectedResult = false; + actualResult = FindElementInArray.findGivenElementInArrayWithoutUsingStream(array, element); + Assert.assertEquals(expectedResult, actualResult); + } + + @Test + public void givenAnIntArray_whenUsingStream_thenFindAnElement() { + int[] array = { 15, 16, 12, 18 }; + int element = 16; + boolean expectedResult = true; + boolean actualResult = FindElementInArray.findGivenElementInArrayUsingStream(array, element); + Assert.assertEquals(expectedResult, actualResult); + + element = 20; + expectedResult = false; + actualResult = FindElementInArray.findGivenElementInArrayUsingStream(array, element); + Assert.assertEquals(expectedResult, actualResult); + } + +} diff --git a/core-java/src/test/java/com/baeldung/array/SumAndAverageInArrayTest.java b/core-java/src/test/java/com/baeldung/array/SumAndAverageInArrayTest.java new file mode 100644 index 0000000000..3385ed690f --- /dev/null +++ b/core-java/src/test/java/com/baeldung/array/SumAndAverageInArrayTest.java @@ -0,0 +1,41 @@ +package com.baeldung.array; + +import org.junit.Assert; +import org.junit.Test; + +public class SumAndAverageInArrayTest { + @Test + public void givenAnIntArray_whenNotUsingStream_thenFindSum() { + int[] array = { 1, 3, 4, 8, 19, 20 }; + int expectedSumOfArray = 55; + int actualSumOfArray = SumAndAverageInArray.findSumWithoutUsingStream(array); + Assert.assertEquals(expectedSumOfArray, actualSumOfArray); + } + + @Test + public void givenAnIntArray_whenUsingStream_thenFindSum() { + int[] array = { 1, 3, 4, 8, 19, 20 }; + int expectedSumOfArray = 55; + int actualSumOfArray = SumAndAverageInArray.findSumUsingStream(array); + + Assert.assertEquals(expectedSumOfArray, actualSumOfArray); + } + + @Test + public void givenAnIntArray_whenNotUsingStream_thenFindAverage() { + int[] array = { 1, 3, 4, 8, 19, 20 }; + double expectedAvgOfArray = 9.17; + double actualAvgOfArray = SumAndAverageInArray.findAverageWithoutUsingStream(array); + + Assert.assertEquals(expectedAvgOfArray, actualAvgOfArray, 0.0034); + } + + @Test + public void givenAnIntArray_whenUsingStream_thenFindAverage() { + int[] array = { 1, 3, 4, 8, 19, 20 }; + double expectedAvgOfArray = 9.17; + double actualAvgOfArray = SumAndAverageInArray.findAverageUsingStream(array); + + Assert.assertEquals(expectedAvgOfArray, actualAvgOfArray, 0.0034); + } +} diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 7f68648eba..b8cea19c58 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -20,3 +20,4 @@ - [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions) - [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources) - [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp) +- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) diff --git a/intelliJ/README.md b/intelliJ/README.md deleted file mode 100644 index ff12555376..0000000000 --- a/intelliJ/README.md +++ /dev/null @@ -1 +0,0 @@ -## Relevant articles: diff --git a/jsonld/.gitignore b/jsonld/.gitignore deleted file mode 100644 index 2af7cefb0a..0000000000 --- a/jsonld/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ \ No newline at end of file diff --git a/jsonld/.mvn/wrapper/maven-wrapper.jar b/jsonld/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 5fd4d5023f..0000000000 Binary files a/jsonld/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/jsonld/.mvn/wrapper/maven-wrapper.properties b/jsonld/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index c954cec91c..0000000000 --- a/jsonld/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip diff --git a/jsonld/README.md b/jsonld/README.md deleted file mode 100644 index 51ca961bea..0000000000 --- a/jsonld/README.md +++ /dev/null @@ -1,22 +0,0 @@ -JSON-LD -======= - -Hypermedia serialization with JSON-LD. - -### Requirements - -- Maven -- JDK 8 -- JSON-LD - -### Running -To build and start the server simply type - -```bash -$ mvn clean install -$ mvn spring-boot:run -``` - -Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) - -Enjoy it :) \ No newline at end of file diff --git a/jsonld/mvnw b/jsonld/mvnw deleted file mode 100755 index a1ba1bf554..0000000000 --- a/jsonld/mvnw +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # - # Look for the Apple JDKs first to preserve the existing behaviour, and then look - # for the new JDKs provided by Oracle. - # - if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then - # - # Apple JDKs - # - export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then - # - # Apple JDKs - # - export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then - # - # Oracle JDKs - # - export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then - # - # Apple JDKs - # - export JAVA_HOME=`/usr/libexec/java_home` - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Migwn, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - local basedir=$(pwd) - local wdir=$(pwd) - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - wdir=$(cd "$wdir/.."; pwd) - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} "$@" diff --git a/jsonld/mvnw.cmd b/jsonld/mvnw.cmd deleted file mode 100644 index 2b934e89dd..0000000000 --- a/jsonld/mvnw.cmd +++ /dev/null @@ -1,145 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -set MAVEN_CMD_LINE_ARGS=%* - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" - -set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% \ No newline at end of file diff --git a/jsonld/pom.xml b/jsonld/pom.xml deleted file mode 100644 index 1574878667..0000000000 --- a/jsonld/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - - jsonld - 0.0.1-SNAPSHOT - jar - - jsonld - Hypermedia serialization with JSON-LD - - - parent-boot-5 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-5 - - - - UTF-8 - UTF-8 - 1.8 - 0.11.1 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-test - test - - - - com.github.jsonld-java - jsonld-java - ${jsonld.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/jsonld/src/main/java/com/baeldung/JsonLdApplication.java b/jsonld/src/main/java/com/baeldung/JsonLdApplication.java deleted file mode 100644 index 0b8f338127..0000000000 --- a/jsonld/src/main/java/com/baeldung/JsonLdApplication.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class JsonLdApplication { - public static void main(String[] args) { - SpringApplication.run(JsonLdApplication.class, args); - } -} diff --git a/jsonld/src/main/resources/application.properties b/jsonld/src/main/resources/application.properties deleted file mode 100644 index b6bfd8f6f3..0000000000 --- a/jsonld/src/main/resources/application.properties +++ /dev/null @@ -1,14 +0,0 @@ -# the db host -spring.data.mongodb.host=localhost -# the connection port (defaults to 27107) -spring.data.mongodb.port=27017 -# The database's name -spring.data.mongodb.database=Jenkins-Pipeline - -# Or this -# spring.data.mongodb.uri=mongodb://localhost/Jenkins-Pipeline - -# spring.data.mongodb.username= -# spring.data.mongodb.password= - -spring.data.mongodb.repositories.enabled=true \ No newline at end of file diff --git a/jsonld/src/test/java/com/baeldung/JsonLdSerializatorTest.java b/jsonld/src/test/java/com/baeldung/JsonLdSerializatorTest.java deleted file mode 100644 index 762a4254dc..0000000000 --- a/jsonld/src/test/java/com/baeldung/JsonLdSerializatorTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung; - -import com.github.jsonldjava.core.JsonLdError; -import com.github.jsonldjava.core.JsonLdOptions; -import com.github.jsonldjava.core.JsonLdProcessor; -import com.github.jsonldjava.utils.JsonUtils; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertNotEquals; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -public class JsonLdSerializatorTest { - - @Test - public void whenInserting_andCount_thenWeDontGetZero() throws JsonLdError { - String inputStream = "{name:}"; - Object jsonObject = JsonUtils.fromInputStream(inputStream); - - Map context = new HashMap(); - JsonLdOptions options = new JsonLdOptions(); - Object compact = JsonLdProcessor.compact(jsonObject, context, options); - - assertNotEquals(0, 0); - } - -} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProcessor.java similarity index 85% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProcessor.java index b86a572393..374de31ba9 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProcessor.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public abstract class AuthenticationProcessor { diff --git a/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProvider.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProvider.java new file mode 100644 index 0000000000..7b8771ca41 --- /dev/null +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/AuthenticationProvider.java @@ -0,0 +1,5 @@ +package com.baeldung.pattern.chainofresponsibility; + +public interface AuthenticationProvider { + +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthAuthenticationProcessor.java similarity index 90% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthAuthenticationProcessor.java index 2e2e51fed2..3bf20cfc85 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthAuthenticationProcessor.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public class OAuthAuthenticationProcessor extends AuthenticationProcessor { diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthTokenProvider.java similarity index 54% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthTokenProvider.java index d4e516053b..92d5f94245 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/OAuthTokenProvider.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public class OAuthTokenProvider implements AuthenticationProvider { diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/SamlAuthenticationProvider.java similarity index 57% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/SamlAuthenticationProvider.java index 533b2b4a2d..cd927932ad 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/SamlAuthenticationProvider.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public class SamlAuthenticationProvider implements AuthenticationProvider { diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java similarity index 90% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java index df600c35db..3885b2b79b 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public class UsernamePasswordAuthenticationProcessor extends AuthenticationProcessor { diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordProvider.java similarity index 56% rename from core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java rename to patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordProvider.java index 9fbfa7554d..9877039446 100644 --- a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java +++ b/patterns/behavioral-patterns/src/main/java/com/baeldung/pattern/chainofresponsibility/UsernamePasswordProvider.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; public class UsernamePasswordProvider implements AuthenticationProvider { diff --git a/core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java b/patterns/behavioral-patterns/src/test/java/com/baeldung/pattern/chainofresponsibility/ChainOfResponsibilityTest.java similarity index 95% rename from core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java rename to patterns/behavioral-patterns/src/test/java/com/baeldung/pattern/chainofresponsibility/ChainOfResponsibilityTest.java index a28577efb1..a84f9dd8e5 100644 --- a/core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java +++ b/patterns/behavioral-patterns/src/test/java/com/baeldung/pattern/chainofresponsibility/ChainOfResponsibilityTest.java @@ -1,4 +1,4 @@ -package com.baeldung.designpatterns.chainofresponsibility; +package com.baeldung.pattern.chainofresponsibility; import org.junit.Test; diff --git a/persistence-modules/java-jdbi/README.md b/persistence-modules/java-jdbi/README.md new file mode 100644 index 0000000000..3bab6faa29 --- /dev/null +++ b/persistence-modules/java-jdbi/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Guide to CockroachDB in Java](http://www.baeldung.com/cockroachdb-java) diff --git a/persistence-modules/java-jdbi/pom.xml b/persistence-modules/java-jdbi/pom.xml new file mode 100644 index 0000000000..392f0bdcbf --- /dev/null +++ b/persistence-modules/java-jdbi/pom.xml @@ -0,0 +1,40 @@ + + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + 4.0.0 + + java-jdbi + 1.0-SNAPSHOT + + + + org.jdbi + jdbi3-core + 3.1.0 + + + org.hsqldb + hsqldb + 2.4.0 + test + + + + + + Central + Central + http://repo1.maven.org/maven2/ + default + + + \ No newline at end of file diff --git a/persistence-modules/java-jdbi/src/test/java/com/baeldung/persistence/jdbi/JdbiTest.java b/persistence-modules/java-jdbi/src/test/java/com/baeldung/persistence/jdbi/JdbiTest.java new file mode 100644 index 0000000000..503bf90fdb --- /dev/null +++ b/persistence-modules/java-jdbi/src/test/java/com/baeldung/persistence/jdbi/JdbiTest.java @@ -0,0 +1,338 @@ +package com.baeldung.persistence.jdbi; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.result.ResultProducer; +import org.jdbi.v3.core.statement.Query; +import org.jdbi.v3.core.statement.StatementContext; +import org.jdbi.v3.core.statement.Update; +import org.junit.Test; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.*; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class JdbiTest { + + @Test + public void whenJdbiCreated_thenSuccess() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + + Jdbi.create("WRONG"); + } + + @Test + public void whenJdbiWithProperties_thenSuccess() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.open().close(); + Properties properties = new Properties(); + properties.setProperty("username", "sa"); + properties.setProperty("password", ""); + jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", properties); + jdbi.open().close(); + } + + @Test + public void whenHandle_thenBoh() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + final Handle[] handleRef = new Handle[1]; + boolean closed = jdbi.withHandle(handle -> { + handleRef[0] = handle; + return handle.isClosed(); + }); + + assertFalse(closed); + assertTrue(handleRef[0].isClosed()); + } + + @Test + public void whenTableCreated_thenInsertIsPossible() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + int updateCount = handle.execute("create table PROJECT_1 (id integer identity, name varchar(50), url varchar(100))"); + + assertEquals(0, updateCount); + + updateCount = handle.execute("INSERT INTO PROJECT_1 VALUES (1, 'tutorials', 'github.com/eugenp/tutorials')"); + + assertEquals(1, updateCount); + }); + } + + @Test + public void whenIdentityColumn_thenInsertReturnsNewId() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + Update update = handle.createUpdate( + "INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + ResultBearing generatedKeys = update.executeAndReturnGeneratedKeys(); + + assertEquals(0, generatedKeys.mapToMap().findOnly().get("id")); + + update = handle.createUpdate( + "INSERT INTO PROJECT_2 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + + assertEquals(1, generatedKeys.mapToMap().findOnly().get("id")); + }); + } + + @Test + public void whenSelectMapToMap_thenResultsAreMapEntries() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + Query query = handle.createQuery("select * from PROJECT_3 order by id"); + List> list = query.mapToMap().list(); + + assertEquals("tutorials", list.get(0).get("name")); + assertEquals("REST with Spring", list.get(1).get("name")); + }); + } + + @Test + public void whenSelectMapToString_thenResultIsString() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + Query query = handle.createQuery("select name, url from PROJECT_4 order by id"); + List list = query.mapTo(String.class).list(); + + assertEquals("tutorials", list.get(0)); + assertEquals("REST with Spring", list.get(1)); + }); + } + + @Test + public void whenSelectMapToString_thenStream() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + Query query = handle.createQuery("select name, url from PROJECT_5 order by id"); + query.mapTo(String.class).useStream((Stream stream) -> assertEquals("tutorials", stream.findFirst().get())); + }); + } + + @Test + public void whenNoResults_thenFindFirstReturnsNone() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + + assertFalse(handle.createQuery("select * from project_6").mapToMap().findFirst().isPresent()); + }); + } + + @Test + public void whenMultipleResults_thenFindFirstReturnsFirst() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_7 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_7 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_7 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + + Query query = handle.createQuery("select * from project_7 order by id"); + Optional> first = query.mapToMap().findFirst(); + + assertTrue(first.isPresent()); + assertEquals("tutorials", first.get().get("name")); + }); + } + + @Test + public void whenNoResults_thenFindOnlyThrows() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_8 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + + try { + handle.createQuery("select * from project_8").mapToMap().findOnly(); + + fail("Exception expected"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + @Test + public void whenMultipleResults_thenFindOnlyThrows() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_9 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')"); + + try { + Query query = handle.createQuery("select * from project_9"); + Map onlyResult = query.mapToMap().findOnly(); + + fail("Exception expected"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + @Test + public void whenParameters_thenReplacement() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + Update update1 = handle.createUpdate("INSERT INTO PROJECT_10 (NAME, URL) VALUES (?, ?)"); + update1.bind(0, "tutorials"); + update1.bind(1, "github.com/eugenp/tutorials"); + int rows = update1.execute(); + + assertEquals(1, rows); + + Update update2 = handle.createUpdate("INSERT INTO PROJECT_10 (NAME, URL) VALUES (:name, :url)"); + update2.bind("name", "REST with Spring"); + update2.bind("url", "github.com/eugenp/REST-With-Spring"); + rows = update2.execute(); + + assertEquals(1, rows); + + List> list = + handle.select("SELECT * FROM PROJECT_10 WHERE NAME = 'tutorials'").mapToMap().list(); + + assertEquals(1, list.size()); + + list = handle.select("SELECT * FROM PROJECT_10 WHERE NAME = 'REST with Spring'").mapToMap().list(); + + assertEquals(1, list.size()); + }); + } + + @Test + public void whenMultipleParameters_thenReplacement() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.execute("create table PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + Update update = handle.createUpdate("INSERT INTO PROJECT_11 (NAME, URL) VALUES (:name, :url)"); + Map params = new HashMap<>(); + params.put("name", "REST with Spring"); + params.put("url", "github.com/eugenp/REST-With-Spring"); + update.bindMap(params); + int rows = update.execute(); + + assertEquals(1, rows); + + List> list = + handle.select("SELECT * FROM PROJECT_11").mapToMap().list(); + + assertEquals(1, list.size()); + + class Params { + private String name; + private String url; + + public Params(String name, String url) { + this.name = name; + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + } + + update.bindBean(new Params("tutorials", "github.com/eugenp/tutorials")); + rows = update.execute(); + + assertEquals(1, rows); + + list = handle.select("SELECT * FROM PROJECT_11").mapToMap().list(); + + assertEquals(2, list.size()); + }); + } + + @Test + public void whenTransactionRollback_thenNoDataInserted() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.useTransaction(h -> { + handle.execute("create table PROJECT_12 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_12 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_12 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')"); + handle.rollback(); + List> list = handle.select("SELECT * FROM PROJECT_12").mapToMap().list(); + + assertEquals(0, list.size()); + }); + }); + } + + @Test + public void whenTransactionRollbackThenCommit_thenOnlyLastInserted() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + handle.useTransaction((Handle h) -> { + assertEquals(handle, h); + + handle.execute("create table PROJECT_13 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + handle.execute("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')"); + handle.rollback(); + handle.begin(); + handle.execute("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')"); + handle.rollback(); + handle.begin(); + handle.execute("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')"); + handle.execute("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')"); + handle.commit(); + }); + List> list = handle.select("SELECT * FROM PROJECT_13").mapToMap().list(); + + assertEquals(2, list.size()); + }); + } + + + @Test + public void whenException_thenTransactionIsRolledBack() { + Jdbi jdbi = Jdbi.create("jdbc:hsqldb:mem:testDB", "sa", ""); + jdbi.useHandle(handle -> { + try { + handle.useTransaction(h -> { + h.execute("create table PROJECT_14 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"); + h.execute("INSERT INTO PROJECT_14 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')"); + List> list = handle.select("SELECT * FROM PROJECT_14").mapToMap().list(); + + assertTrue(h.isInTransaction()); + assertEquals(1, list.size()); + + throw new Exception("rollback"); + }); + } catch (Exception ignored) {} + List> list = handle.select("SELECT * FROM PROJECT_14").mapToMap().list(); + + assertFalse(handle.isInTransaction()); + assertEquals(0, list.size()); + }); + } + +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/config/StudentJpaConfig.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/config/StudentJpaConfig.java index 8021691716..17047cbab2 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/config/StudentJpaConfig.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/config/StudentJpaConfig.java @@ -25,7 +25,7 @@ public class StudentJpaConfig { @Autowired private Environment env; - + @Bean public DataSource dataSource() { final DriverManagerDataSource dataSource = new DriverManagerDataSource(); @@ -36,7 +36,7 @@ public class StudentJpaConfig { return dataSource; } - + @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); @@ -46,23 +46,23 @@ public class StudentJpaConfig { em.setJpaProperties(additionalProperties()); return em; } - + @Bean JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; } - + final Properties additionalProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); - hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache")); hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache")); - + return hibernateProperties; } } diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/dsrouting/ClientDao.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/dsrouting/ClientDao.java index 180f54326e..9e19cf4ed9 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/dsrouting/ClientDao.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/dsrouting/ClientDao.java @@ -19,8 +19,7 @@ public class ClientDao { } public String getClientName() { - return this.jdbcTemplate.query(SQL_GET_CLIENT_NAME, rowMapper) - .get(0); + return this.jdbcTemplate.query(SQL_GET_CLIENT_NAME, rowMapper).get(0); } private static RowMapper rowMapper = (rs, rowNum) -> { diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/extended/persistence/dao/ExtendedRepositoryImpl.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/extended/persistence/dao/ExtendedRepositoryImpl.java index 0dd32757d7..7ed652dc4d 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/extended/persistence/dao/ExtendedRepositoryImpl.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/extended/persistence/dao/ExtendedRepositoryImpl.java @@ -27,8 +27,7 @@ public class ExtendedRepositoryImpl extends SimpleJp CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery query = builder.createQuery(getDomainClass()); Root root = query.from(getDomainClass()); - query.select(root) - .where(builder.like(root. get(attributeName), "%" + text + "%")); + query.select(root).where(builder.like(root. get(attributeName), "%" + text + "%")); TypedQuery q = entityManager.createQuery(query); return q.getResultList(); } diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java new file mode 100644 index 0000000000..a03b2950a0 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.inmemory.persistence.dao; + +import org.baeldung.inmemory.persistence.model.ManyStudent; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ManyStudentRepository extends JpaRepository { + List findByManyTags_Name(String name); +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java new file mode 100644 index 0000000000..b7d991de32 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java @@ -0,0 +1,7 @@ +package org.baeldung.inmemory.persistence.dao; + +import org.baeldung.inmemory.persistence.model.ManyTag; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ManyTagRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java index f856b78c52..ffe1a68558 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java @@ -15,4 +15,10 @@ public interface StudentRepository extends JpaRepository { @Query("SELECT s FROM Student s JOIN s.tags t WHERE s.name = LOWER(:name) AND t = LOWER(:tag)") List retrieveByNameFilterByTag(@Param("name") String name, @Param("tag") String tag); + @Query("SELECT s FROM Student s JOIN s.skillTags t WHERE t.name = LOWER(:tagName) AND t.value > :tagValue") + List retrieveByNameFilterByMinimumSkillTag(@Param("tagName") String tagName, @Param("tagValue") int tagValue); + + @Query("SELECT s FROM Student s JOIN s.kvTags t WHERE t.key = LOWER(:key)") + List retrieveByKeyTag(@Param("key") String key); + } diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java new file mode 100644 index 0000000000..1522744116 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java @@ -0,0 +1,34 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class KVTag { + private String key; + private String value; + + public KVTag() { + } + + public KVTag(String key, String value) { + super(); + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java new file mode 100644 index 0000000000..3acdbbe6fe --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java @@ -0,0 +1,40 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class LocationTag { + private String name; + private int xPos; + private int yPos; + + public LocationTag() { + } + + public LocationTag(String name, int xPos, int yPos) { + super(); + this.name = name; + this.xPos = xPos; + this.yPos = yPos; + } + + public String getName() { + return name; + } + + public int getxPos() { + return xPos; + } + + public void setxPos(int xPos) { + this.xPos = xPos; + } + + public int getyPos() { + return yPos; + } + + public void setyPos(int yPos) { + this.yPos = yPos; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java new file mode 100644 index 0000000000..8343edc9cd --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java @@ -0,0 +1,33 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class ManyStudent { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String name; + + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable(name = "manystudent_manytags", joinColumns = @JoinColumn(name = "manystudent_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "manytag_id", referencedColumnName = "id")) + private Set manyTags = new HashSet<>(); + + public ManyStudent() { + } + + public ManyStudent(String name) { + this.name = name; + } + + public Set getManyTags() { + return manyTags; + } + + public void setManyTags(Set manyTags) { + this.manyTags.addAll(manyTags); + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java new file mode 100644 index 0000000000..e820506544 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java @@ -0,0 +1,40 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class ManyTag { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String name; + + @ManyToMany(mappedBy = "manyTags") + private Set students = new HashSet<>(); + + public ManyTag() { + } + + public ManyTag(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getStudents() { + return students; + } + + public void setStudents(Set students) { + this.students.addAll(students); + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java new file mode 100644 index 0000000000..490ee0a18e --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java @@ -0,0 +1,30 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class SkillTag { + private String name; + private int value; + + public SkillTag() { + } + + public SkillTag(String name, int value) { + super(); + this.name = name; + this.value = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public String getName() { + return name; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java index 2e4e3ea2cb..07aa3ef9ef 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java @@ -1,10 +1,10 @@ package org.baeldung.inmemory.persistence.model; +import java.util.ArrayList; +import java.util.List; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.Id; -import java.util.ArrayList; -import java.util.List; @Entity public class Student { @@ -16,6 +16,12 @@ public class Student { @ElementCollection private List tags = new ArrayList<>(); + @ElementCollection + private List skillTags = new ArrayList<>(); + + @ElementCollection + private List kvTags = new ArrayList<>(); + public Student() { } @@ -48,4 +54,21 @@ public class Student { public void setTags(List tags) { this.tags.addAll(tags); } + + public List getSkillTags() { + return skillTags; + } + + public void setSkillTags(List skillTags) { + this.skillTags.addAll(skillTags); + } + + public List getKVTags() { + return this.kvTags; + } + + public void setKVTags(List kvTags) { + this.kvTags.addAll(kvTags); + } + } diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/sqlfiles/Country.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/sqlfiles/Country.java index 0555c8186c..922f55cbf6 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/sqlfiles/Country.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/sqlfiles/Country.java @@ -13,21 +13,24 @@ public class Country { @Id @GeneratedValue(strategy = IDENTITY) private Integer id; - + @Column(nullable = false) private String name; - + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } - + } diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/dsrouting/DataSourceRoutingTestConfiguration.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/dsrouting/DataSourceRoutingTestConfiguration.java index dee9d58722..faad1695f4 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/dsrouting/DataSourceRoutingTestConfiguration.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/dsrouting/DataSourceRoutingTestConfiguration.java @@ -7,7 +7,6 @@ import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @@ -35,17 +34,11 @@ public class DataSourceRoutingTestConfiguration { private DataSource clientADatasource() { EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder(); - return dbBuilder.setType(EmbeddedDatabaseType.H2) - .setName("CLIENT_A") - .addScript("classpath:dsrouting-db.sql") - .build(); + return dbBuilder.setType(EmbeddedDatabaseType.H2).setName("CLIENT_A").addScript("classpath:dsrouting-db.sql").build(); } private DataSource clientBDatasource() { EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder(); - return dbBuilder.setType(EmbeddedDatabaseType.H2) - .setName("CLIENT_B") - .addScript("classpath:dsrouting-db.sql") - .build(); + return dbBuilder.setType(EmbeddedDatabaseType.H2).setName("CLIENT_B").addScript("classpath:dsrouting-db.sql").build(); } } diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/config/PersistenceJPAConfigDeletion.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/config/PersistenceJPAConfigDeletion.java index 37388d1c51..09d118fedc 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/config/PersistenceJPAConfigDeletion.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/config/PersistenceJPAConfigDeletion.java @@ -2,8 +2,6 @@ package org.baeldung.persistence.deletion.config; import org.baeldung.config.PersistenceJPAConfigL2Cache; -import java.util.Properties; - public class PersistenceJPAConfigDeletion extends PersistenceJPAConfigL2Cache { public PersistenceJPAConfigDeletion() { diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/model/Baz.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/model/Baz.java index 2dad3e6654..4fb3f8965e 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/model/Baz.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/deletion/model/Baz.java @@ -1,7 +1,6 @@ package org.baeldung.persistence.deletion.model; import javax.persistence.*; -import java.util.List; @Entity @Table(name = "BAZ") diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/AdvancedTaggingIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/AdvancedTaggingIntegrationTest.java new file mode 100644 index 0000000000..9432420878 --- /dev/null +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/AdvancedTaggingIntegrationTest.java @@ -0,0 +1,81 @@ +package org.baeldung.persistence.repository; + +import org.baeldung.config.StudentJpaConfig; +import org.baeldung.inmemory.persistence.dao.ManyStudentRepository; +import org.baeldung.inmemory.persistence.dao.ManyTagRepository; +import org.baeldung.inmemory.persistence.dao.StudentRepository; +import org.baeldung.inmemory.persistence.model.KVTag; +import org.baeldung.inmemory.persistence.model.ManyStudent; +import org.baeldung.inmemory.persistence.model.ManyTag; +import org.baeldung.inmemory.persistence.model.SkillTag; +import org.baeldung.inmemory.persistence.model.Student; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { StudentJpaConfig.class }, loader = AnnotationConfigContextLoader.class) +@Transactional +public class AdvancedTaggingIntegrationTest { + @Resource + private StudentRepository studentRepository; + + @Resource + private ManyStudentRepository manyStudentRepository; + + @Resource + private ManyTagRepository manyTagRepository; + + @Test + public void givenStudentWithSkillTags_whenSave_thenGetByNameAndSkillTag() { + Student student = new Student(1, "Will"); + SkillTag skill1 = new SkillTag("java", 5); + student.setSkillTags(Arrays.asList(skill1)); + studentRepository.save(student); + + Student student2 = new Student(2, "Joe"); + SkillTag skill2 = new SkillTag("java", 1); + student2.setSkillTags(Arrays.asList(skill2)); + studentRepository.save(student2); + + List students = studentRepository.retrieveByNameFilterByMinimumSkillTag("java", 3); + assertEquals("size incorrect", 1, students.size()); + } + + @Test + public void givenStudentWithKVTags_whenSave_thenGetByTagOk() { + Student student = new Student(0, "John"); + student.setKVTags(Arrays.asList(new KVTag("department", "computer science"))); + studentRepository.save(student); + + Student student2 = new Student(1, "James"); + student2.setKVTags(Arrays.asList(new KVTag("department", "humanities"))); + studentRepository.save(student2); + + List students = studentRepository.retrieveByKeyTag("department"); + assertEquals("size incorrect", 2, students.size()); + } + + @Test + public void givenStudentWithManyTags_whenSave_theyGetByTagOk() { + ManyTag tag = new ManyTag("full time"); + manyTagRepository.save(tag); + + ManyStudent student = new ManyStudent("John"); + student.setManyTags(Collections.singleton(tag)); + manyStudentRepository.save(student); + + List students = manyStudentRepository.findByManyTags_Name("full time"); + assertEquals("size incorrect", 1, students.size()); + } +} diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/ExtendedStudentRepositoryIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/ExtendedStudentRepositoryIntegrationTest.java index 0970daa0ee..7c6ec9b6da 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/ExtendedStudentRepositoryIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/ExtendedStudentRepositoryIntegrationTest.java @@ -16,13 +16,13 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { StudentJPAH2Config.class}) +@ContextConfiguration(classes = { StudentJPAH2Config.class }) public class ExtendedStudentRepositoryIntegrationTest { @Resource private ExtendedStudentRepository extendedStudentRepository; - + @Before - public void setup(){ + public void setup() { Student student = new Student(1, "john"); extendedStudentRepository.save(student); Student student2 = new Student(2, "johnson"); @@ -30,10 +30,10 @@ public class ExtendedStudentRepositoryIntegrationTest { Student student3 = new Student(3, "tom"); extendedStudentRepository.save(student3); } - + @Test - public void givenStudents_whenFindByName_thenGetOk(){ + public void givenStudents_whenFindByName_thenGetOk() { List students = extendedStudentRepository.findByAttributeContainsText("name", "john"); - assertThat(students.size()).isEqualTo(2); + assertThat(students.size()).isEqualTo(2); } } diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java index 28d7e3772c..3d9e376e81 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java @@ -21,24 +21,24 @@ import static org.junit.Assert.assertEquals; @ContextConfiguration(classes = { StudentJpaConfig.class }, loader = AnnotationConfigContextLoader.class) @Transactional public class InMemoryDBIntegrationTest { - + @Resource private StudentRepository studentRepository; - + private static final long ID = 1; - private static final String NAME="john"; - + private static final String NAME = "john"; + @Test - public void givenStudent_whenSave_thenGetOk(){ + public void givenStudent_whenSave_thenGetOk() { Student student = new Student(ID, NAME); studentRepository.save(student); - + Student student2 = studentRepository.findOne(ID); - assertEquals("name incorrect", NAME, student2.getName()); + assertEquals("name incorrect", NAME, student2.getName()); } @Test - public void givenStudentWithTags_whenSave_thenGetByTagOk(){ + public void givenStudentWithTags_whenSave_thenGetByTagOk() { Student student = new Student(ID, NAME); student.setTags(Arrays.asList("full time", "computer science")); studentRepository.save(student); @@ -48,7 +48,7 @@ public class InMemoryDBIntegrationTest { } @Test - public void givenMultipleStudentsWithTags_whenSave_thenGetByTagReturnsCorrectCount(){ + public void givenMultipleStudentsWithTags_whenSave_thenGetByTagReturnsCorrectCount() { Student student = new Student(0, "Larry"); student.setTags(Arrays.asList("full time", "computer science")); studentRepository.save(student); @@ -70,7 +70,7 @@ public class InMemoryDBIntegrationTest { } @Test - public void givenStudentWithTags_whenSave_thenGetByNameAndTagOk(){ + public void givenStudentWithTags_whenSave_thenGetByNameAndTagOk() { Student student = new Student(ID, NAME); student.setTags(Arrays.asList("full time", "computer science")); studentRepository.save(student); diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/service/DeletionIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/service/DeletionIntegrationTest.java index 9e5c5fa07a..f42a4e9be1 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/service/DeletionIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/service/DeletionIntegrationTest.java @@ -117,9 +117,7 @@ public class DeletionIntegrationTest { entityManager.persist(foo); flushAndClear(); - entityManager.createQuery("delete from Foo where id = :id") - .setParameter("id", foo.getId()) - .executeUpdate(); + entityManager.createQuery("delete from Foo where id = :id").setParameter("id", foo.getId()).executeUpdate(); assertThat(entityManager.find(Foo.class, foo.getId()), nullValue()); } @@ -131,9 +129,7 @@ public class DeletionIntegrationTest { entityManager.persist(foo); flushAndClear(); - entityManager.createNativeQuery("delete from FOO where ID = :id") - .setParameter("id", foo.getId()) - .executeUpdate(); + entityManager.createNativeQuery("delete from FOO where ID = :id").setParameter("id", foo.getId()).executeUpdate(); assertThat(entityManager.find(Foo.class, foo.getId()), nullValue()); } diff --git a/pom.xml b/pom.xml index 463f060240..70a3bbc5b4 100644 --- a/pom.xml +++ b/pom.xml @@ -280,6 +280,7 @@ lucene vraptor persistence-modules/java-cockroachdb + persistence-modules/java-jdbi jersey java-spi diff --git a/reactor-core/src/test/java/com/baeldung/reactor/core/CombiningPublishersTest.java b/reactor-core/src/test/java/com/baeldung/reactor/core/CombiningPublishersTest.java index 81dfda3bb3..41769b1b35 100644 --- a/reactor-core/src/test/java/com/baeldung/reactor/core/CombiningPublishersTest.java +++ b/reactor-core/src/test/java/com/baeldung/reactor/core/CombiningPublishersTest.java @@ -15,28 +15,28 @@ public class CombiningPublishersTest { private static Flux evenNumbers = Flux.range(min, max).filter(x -> x % 2 == 0); private static Flux oddNumbers = Flux.range(min, max).filter(x -> x % 2 > 0); - @Test - public void givenFluxes_whenMergeIsInvoked_thenMerge() { - Flux fluxOfIntegers = Flux.merge( - evenNumbers, - oddNumbers); + public void givenFluxes_whenMergeDelayErrorIsInvoked_thenMergeDelayError() { + Flux fluxOfIntegers = Flux.mergeDelayError(1, + evenNumbers.delayElements(Duration.ofMillis(2000L)), + oddNumbers.delayElements(Duration.ofMillis(1000L))); StepVerifier.create(fluxOfIntegers) - .expectNext(2) - .expectNext(4) .expectNext(1) + .expectNext(2) .expectNext(3) .expectNext(5) + .expectNext(4) .expectComplete() .verify(); } + @Test public void givenFluxes_whenMergeWithDelayedElementsIsInvoked_thenMergeWithDelayedElements() { Flux fluxOfIntegers = Flux.merge( - evenNumbers.delayElements(Duration.ofMillis(500L)), - oddNumbers.delayElements(Duration.ofMillis(300L))); + evenNumbers.delayElements(Duration.ofMillis(2000L)), + oddNumbers.delayElements(Duration.ofMillis(1000L))); StepVerifier.create(fluxOfIntegers) .expectNext(1) @@ -51,8 +51,24 @@ public class CombiningPublishersTest { @Test public void givenFluxes_whenConcatIsInvoked_thenConcat() { Flux fluxOfIntegers = Flux.concat( - evenNumbers.delayElements(Duration.ofMillis(500L)), - oddNumbers.delayElements(Duration.ofMillis(300L))); + evenNumbers.delayElements(Duration.ofMillis(2000L)), + oddNumbers.delayElements(Duration.ofMillis(1000L))); + + StepVerifier.create(fluxOfIntegers) + .expectNext(2) + .expectNext(4) + .expectNext(1) + .expectNext(3) + .expectNext(5) + .expectComplete() + .verify(); + } + + @Test + public void givenFluxes_whenMergeIsInvoked_thenMerge() { + Flux fluxOfIntegers = Flux.merge( + evenNumbers, + oddNumbers); StepVerifier.create(fluxOfIntegers) .expectNext(2) @@ -121,22 +137,6 @@ public class CombiningPublishersTest { } - @Test - public void givenFluxes_whenMergeDelayErrorIsInvoked_thenMergeDelayError() { - Flux fluxOfIntegers = Flux.mergeDelayError(1, - evenNumbers.delayElements(Duration.ofMillis(500L)), - oddNumbers.delayElements(Duration.ofMillis(300L))); - - StepVerifier.create(fluxOfIntegers) - .expectNext(1) - .expectNext(2) - .expectNext(3) - .expectNext(5) - .expectNext(4) - .expectComplete() - .verify(); - } - @Test public void givenFluxes_whenMergeWithIsInvoked_thenMergeWith() { Flux fluxOfIntegers = evenNumbers.mergeWith(oddNumbers); @@ -177,4 +177,4 @@ public class CombiningPublishersTest { .expectComplete() .verify(); } -} +} \ No newline at end of file diff --git a/rxjava/src/test/java/com/baeldung/rxjava/MaybeTest.java b/rxjava/src/test/java/com/baeldung/rxjava/MaybeTest.java new file mode 100644 index 0000000000..501ee1f196 --- /dev/null +++ b/rxjava/src/test/java/com/baeldung/rxjava/MaybeTest.java @@ -0,0 +1,40 @@ +package com.baeldung.rxjava; + +import org.junit.Test; + +import io.reactivex.Flowable; +import io.reactivex.Maybe; + +public class MaybeTest { + @Test + public void whenEmitsSingleValue_thenItIsObserved() { + Maybe maybe = Flowable.just(1, 2, 3, 4, 5) + .firstElement(); + + maybe.map(x -> x + 7) + .filter(x -> x > 0) + .test() + .assertResult(8) + .assertComplete(); + } + + @Test + public void whenEmitsNoValue_thenSignalsCompletionAndNoValueObserved() { + Maybe maybe = Flowable.just(1, 2, 3, 4, 5) + .skip(5) + .firstElement(); + + maybe.test() + .assertComplete() + .assertNoValues(); + } + + @Test + public void whenThrowsError_thenErrorIsRaised() { + Maybe maybe = Flowable. error(new Exception("msg")) + .firstElement(); + + maybe.test() + .assertErrorMessage("msg"); + } +} diff --git a/rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java b/rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java new file mode 100644 index 0000000000..693608d116 --- /dev/null +++ b/rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java @@ -0,0 +1,121 @@ +package com.baeldung.rxjava.combine; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import rx.Observable; +import rx.observers.TestSubscriber; + +public class ObservableCombineUnitTest { + + private static ExecutorService executor; + + @BeforeClass + public static void setupClass() { + executor = Executors.newFixedThreadPool(10); + } + + @AfterClass + public static void tearDownClass() { + executor.shutdown(); + } + + @Test + public void givenTwoObservables_whenMerged_shouldEmitCombinedResults() { + List results = new ArrayList<>(); + + //@formatter:off + Observable.merge( + Observable.from(new String[] {"Hello", "World"}), + Observable.from(new String[]{ "I love", "RxJava"}) + ).subscribe(data -> { + results.add(data); + }); + //@formatter:on + + assertThat(results).isNotEmpty(); + assertThat(results.size()).isEqualTo(4); + assertThat(results).contains("Hello", "World", "I love", "RxJava"); + } + + @Test + public void givenAnObservable_whenStartWith_thenPrependEmittedResults() { + StringBuffer buffer = new StringBuffer(); + + //@formatter:off + Observable + .from(new String[] { "RxJava", "Observables" }) + .startWith("Buzzwords of Reactive Programming") + .subscribe(data -> { + buffer.append(data).append(" "); + }); + //@formatter:on + + assertThat(buffer.toString().trim()).isEqualTo("Buzzwords of Reactive Programming RxJava Observables"); + } + + @Test + public void givenTwoObservables_whenZipped_thenReturnCombinedResults() { + List zippedStrings = new ArrayList<>(); + + //@formatter:off + Observable.zip( + Observable.from(new String[] { "Simple", "Moderate", "Complex" }), + Observable.from(new String[] { "Solutions", "Success", "Heirarchy"}), + (str1, str2) -> { + return str1 + " " + str2; + }).subscribe(zipped -> { + zippedStrings.add(zipped); + }); + //formatter:on + + assertThat(zippedStrings).isNotEmpty(); + assertThat(zippedStrings.size()).isEqualTo(3); + assertThat(zippedStrings).contains("Simple Solutions", "Moderate Success", "Complex Heirarchy"); + } + + @Test + public void givenMutipleObservablesOneThrows_whenMerged_thenCombineBeforePropagatingError() { + Future f1 = executor.submit(createCallable("Hello")); + Future f2 = executor.submit(createCallable("World")); + Future f3 = executor.submit(createCallable(null)); + Future f4 = executor.submit(createCallable("RxJava")); + + TestSubscriber testSubscriber = new TestSubscriber<>(); + + //@formatter:off + Observable.mergeDelayError( + Observable.from(f1), + Observable.from(f2), + Observable.from(f3), + Observable.from(f4) + ).subscribe(testSubscriber); + //@formatter:on + + testSubscriber.assertValues("hello", "world", "rxjava"); + testSubscriber.assertError(ExecutionException.class); + } + + private Callable createCallable(final String data) { + return new Callable() { + @Override + public String call() throws Exception { + if (data == null) { + throw new IllegalArgumentException("Data should not be null."); + } + return data.toLowerCase(); + } + }; + } +} diff --git a/spring-mvc-kotlin/pom.xml b/spring-mvc-kotlin/pom.xml index 28a5681c03..8f9c58854d 100644 --- a/spring-mvc-kotlin/pom.xml +++ b/spring-mvc-kotlin/pom.xml @@ -20,7 +20,7 @@ UTF-8 5.2.13.Final - 1.2.21 + 1.2.30 4.3.10.RELEASE 3.0.7.RELEASE 1.4.196 diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt index 801bd1b0a5..076dcdac46 100644 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt +++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt @@ -1,15 +1,24 @@ package com.baeldung.jpa +import javax.persistence.CascadeType +import javax.persistence.Column import javax.persistence.Entity +import javax.persistence.FetchType import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id +import javax.persistence.OneToMany import javax.persistence.Table @Entity @Table(name = "person") data class Person( @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Int, - val name: String) \ No newline at end of file + @Column(nullable = false) + val name: String, + @Column(nullable = true) + val email: String?, + @Column(nullable = true) + @OneToMany(fetch = FetchType.LAZY, cascade = [CascadeType.ALL]) val phoneNumbers: List?) \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt new file mode 100644 index 0000000000..25894275f6 --- /dev/null +++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt @@ -0,0 +1,17 @@ +package com.baeldung.jpa + +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.persistence.Table + +@Entity +@Table(name = "phone_number") +data class PhoneNumber( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Int, + @Column(nullable = false) + val number: String) \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt index 8f54373406..94559812fa 100644 --- a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt +++ b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt @@ -1,6 +1,7 @@ package com.baeldung.kotlin.jpa import com.baeldung.jpa.Person +import com.baeldung.jpa.PhoneNumber import org.hibernate.cfg.Configuration import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase import org.hibernate.testing.transaction.TransactionUtil.doInHibernate @@ -21,7 +22,7 @@ class HibernateKotlinIntegrationTest : BaseCoreFunctionalTestCase() { } override fun getAnnotatedClasses(): Array> { - return arrayOf(Person::class.java) + return arrayOf(Person::class.java, PhoneNumber::class.java) } override fun configure(configuration: Configuration) { @@ -31,13 +32,22 @@ class HibernateKotlinIntegrationTest : BaseCoreFunctionalTestCase() { @Test fun givenPerson_whenSaved_thenFound() { - val personToSave = Person(0, "John") doInHibernate(({ this.sessionFactory() }), { session -> + val personToSave = Person(0, "John", "jhon@test.com", Arrays.asList(PhoneNumber(0, "202-555-0171"), PhoneNumber(0, "202-555-0102"))) session.persist(personToSave) - assertTrue(session.contains(personToSave)) - }) - doInHibernate(({ this.sessionFactory() }), { session -> val personFound = session.find(Person::class.java, personToSave.id) + session.refresh(personFound) + assertTrue(personToSave == personFound) + }) + } + + @Test + fun givenPersonWithNullFields_whenSaved_thenFound() { + doInHibernate(({ this.sessionFactory() }), { session -> + val personToSave = Person(0, "John", null, null) + session.persist(personToSave) + val personFound = session.find(Person::class.java, personToSave.id) + session.refresh(personFound) assertTrue(personToSave == personFound) }) } diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index c0e4b63897..a2ba2188d6 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -34,6 +34,7 @@ 2.9.4 1.4.9 5.1.0 + 20180130 @@ -129,18 +130,6 @@ rome ${rome.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson.version} - - com.thoughtworks.xstream xstream @@ -151,6 +140,11 @@ scribejava-apis ${scribejava.version} + + org.json + json + ${json.version} + diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java index 3275d919ea..c4c6791f9a 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java @@ -1,17 +1,13 @@ package com.baeldung.spring.configuration; import com.baeldung.spring.controller.rss.ArticleRssFeedViewResolver; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +import com.baeldung.spring.controller.rss.JsonChannelHttpMessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.feed.RssChannelHttpMessageConverter; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver; @@ -28,7 +24,7 @@ import java.util.List; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator" }) -class ApplicationConfiguration extends WebMvcConfigurerAdapter { +public class ApplicationConfiguration extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { @@ -60,16 +56,9 @@ class ApplicationConfiguration extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List> converters) { - Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml(); - builder.indentOutput(true); - - XmlMapper xmlMapper = builder.createXmlMapper(true).build(); - xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); - converters.add(new StringHttpMessageConverter()); converters.add(new RssChannelHttpMessageConverter()); - converters.add(new MappingJackson2HttpMessageConverter()); - converters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); + converters.add(new JsonChannelHttpMessageConverter()); super.configureMessageConverters(converters); } diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/RssData.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/Article.java similarity index 70% rename from spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/RssData.java rename to spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/Article.java index 258712eb2d..e6e83f95ff 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/RssData.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/Article.java @@ -1,15 +1,14 @@ package com.baeldung.spring.controller.rss; import java.io.Serializable; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Date; -public class RssData implements Serializable { +public class Article implements Serializable { private String link; private String title; private String description; - private String publishedDate; + private Date publishedDate; + private String author; public String getLink() { return link; @@ -35,22 +34,30 @@ public class RssData implements Serializable { this.description = description; } - public String getPublishedDate() { + public Date getPublishedDate() { return publishedDate; } public void setPublishedDate(Date publishedDate) { - DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); - this.publishedDate = df.format(publishedDate); + this.publishedDate = publishedDate; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; } @Override public String toString() { - return "RssData{" + + return "Article{" + "link='" + link + '\'' + ", title='" + title + '\'' + ", description='" + description + '\'' + ", publishedDate=" + publishedDate + + ", author='" + author + '\'' + '}'; } } diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleFeed.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleFeed.java deleted file mode 100644 index 71b225bf3f..0000000000 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleFeed.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.spring.controller.rss; - -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -@JacksonXmlRootElement(localName="articles") -public class ArticleFeed extends RssData implements Serializable { - - @JacksonXmlProperty(localName = "item") - @JacksonXmlElementWrapper(useWrapping = false) - private List items = new ArrayList(); - - public void addItem(ArticleItem articleItem) { - this.items.add(articleItem); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleItem.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleItem.java deleted file mode 100644 index 6c91819676..0000000000 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleItem.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.spring.controller.rss; - -import java.io.Serializable; - -public class ArticleItem extends RssData implements Serializable { - private String author; - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - @Override - public String toString() { - return "ArticleItem{" + - "author='" + author + '\'' + - '}'; - } -} diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java index b0cce99d33..23a6b8700e 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java @@ -1,10 +1,15 @@ package com.baeldung.spring.controller.rss; +import com.rometools.rome.feed.rss.Channel; +import com.rometools.rome.feed.rss.Description; +import com.rometools.rome.feed.rss.Item; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; +import java.util.ArrayList; import java.util.Date; +import java.util.List; @Controller public class ArticleRssController { @@ -14,33 +19,53 @@ public class ArticleRssController { return "articleFeedView"; } - @GetMapping(value = "/rss2") + @GetMapping(value = "/rss2", produces = {"application/rss+xml", "application/rss+json"}) @ResponseBody - public ArticleFeed articleRestFeed2() { - ArticleFeed feed = new ArticleFeed(); - feed.setLink("http://localhost:8080/spring-mvc-simple/rss"); - feed.setTitle("Article Feed"); - feed.setDescription("Article Feed Description"); - feed.setPublishedDate(new Date()); - - ArticleItem item1 = new ArticleItem(); + public Channel articleHttpFeed() { + List
items = new ArrayList<>(); + Article item1 = new Article(); item1.setLink("http://www.baeldung.com/netty-exception-handling"); item1.setTitle("Exceptions in Netty"); item1.setDescription("In this quick article, we’ll be looking at exception handling in Netty."); item1.setPublishedDate(new Date()); item1.setAuthor("Carlos"); - ArticleItem item2 = new ArticleItem(); + Article item2 = new Article(); item2.setLink("http://www.baeldung.com/cockroachdb-java"); item2.setTitle("Guide to CockroachDB in Java"); item2.setDescription("This tutorial is an introductory guide to using CockroachDB with Java."); item2.setPublishedDate(new Date()); item2.setAuthor("Baeldung"); - feed.addItem(item1); - feed.addItem(item2); + items.add(item1); + items.add(item2); + Channel channelData = buildChannel(items); - return feed; + return channelData; + } + + private Channel buildChannel(List
articles){ + Channel channel = new Channel("rss_2.0"); + channel.setLink("http://localhost:8080/spring-mvc-simple/rss"); + channel.setTitle("Article Feed"); + channel.setDescription("Article Feed Description"); + channel.setPubDate(new Date()); + + List items = new ArrayList<>(); + for (Article article : articles) { + Item item = new Item(); + item.setLink(article.getLink()); + item.setTitle(article.getTitle()); + Description description1 = new Description(); + description1.setValue(article.getDescription()); + item.setDescription(description1); + item.setPubDate(article.getPublishedDate()); + item.setAuthor(article.getAuthor()); + items.add(item); + } + + channel.setItems(items); + return channel; } } diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java new file mode 100644 index 0000000000..a32cbbdb7f --- /dev/null +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.controller.rss; + +import com.rometools.rome.feed.rss.Channel; +import com.rometools.rome.io.FeedException; +import com.rometools.rome.io.WireFeedOutput; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.XML; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; + +import java.io.IOException; + +public class JsonChannelHttpMessageConverter extends AbstractHttpMessageConverter { + public JsonChannelHttpMessageConverter(){ + super(new MediaType("application", "rss+json")); + } + + @Override + protected boolean supports(Class aClass) { + return Channel.class.isAssignableFrom(aClass); + } + + @Override + protected Channel readInternal(Class aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException { + return null; + } + + @Override + protected void writeInternal(Channel wireFeed, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { + WireFeedOutput feedOutput = new WireFeedOutput(); + + try { + String xmlStr = feedOutput.outputString(wireFeed, true); + JSONObject xmlJSONObj = XML.toJSONObject(xmlStr); + String jsonPrettyPrintString = xmlJSONObj.toString(4); + + outputMessage.getBody().write(jsonPrettyPrintString.getBytes()); + } catch (JSONException | FeedException e) { + e.printStackTrace(); + } + } +} diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java new file mode 100644 index 0000000000..61b91cbd4d --- /dev/null +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java @@ -0,0 +1,58 @@ +package com.baeldung.spring.controller.scribe; + +import com.github.scribejava.apis.GitHubApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.*; +import com.github.scribejava.core.oauth.OAuth20Service; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.view.RedirectView; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.ExecutionException; + +@Controller +@RequestMapping("github") +public class GithubController { + private OAuth20Service createService(String state) { + return new ServiceBuilder("e1f8d4f1a5c71467a159") + .apiSecret("4851597541a8f33a4f1bf1c70f3cedcfefbeb13b") + .state(state) + .callback("http://localhost:8080/spring-mvc-simple/github/callback") + .build(GitHubApi.instance()); + } + + @GetMapping(value = "/authorization") + public RedirectView authorization(HttpServletRequest servletReq) throws InterruptedException, ExecutionException, IOException { + String state = String.valueOf(new Random().nextInt(999_999)); + OAuth20Service githubService = createService(state); + servletReq.getSession().setAttribute("state", state); + + String authorizationUrl = githubService.getAuthorizationUrl(); + RedirectView redirectView = new RedirectView(); + redirectView.setUrl(authorizationUrl); + return redirectView; + } + + @GetMapping(value = "/callback", produces = "text/plain") + @ResponseBody + public String callback(HttpServletRequest servletReq, @RequestParam("code") String code, @RequestParam("state") String state) throws InterruptedException, ExecutionException, IOException { + String initialState = (String) servletReq.getSession().getAttribute("state"); + if(initialState.equals(state)) { + OAuth20Service githubService = createService(initialState); + OAuth2AccessToken accessToken = githubService.getAccessToken(code); + + OAuthRequest request = new OAuthRequest(Verb.GET, "https://api.github.com/user"); + githubService.signRequest(accessToken, request); + Response response = githubService.execute(request); + + return response.getBody(); + } + return "Error"; + } +} diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/ScribeController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java similarity index 83% rename from spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/ScribeController.java rename to spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java index c5c97ff009..af47797ac5 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/ScribeController.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java @@ -17,18 +17,18 @@ import java.util.concurrent.ExecutionException; @Controller @RequestMapping("twitter") -public class ScribeController { +public class TwitterController { - private OAuth10aService createTwitterService() { + private OAuth10aService createService() { return new ServiceBuilder("PSRszoHhRDVhyo2RIkThEbWko") - .apiSecret("prpJbz03DcGRN46sb4ucdSYtVxG8unUKhcnu3an5ItXbEOuenL") - .callback("http://localhost:8080/spring-mvc-simple/twitter/callback") - .build(TwitterApi.instance()); + .apiSecret("prpJbz03DcGRN46sb4ucdSYtVxG8unUKhcnu3an5ItXbEOuenL") + .callback("http://localhost:8080/spring-mvc-simple/twitter/callback") + .build(TwitterApi.instance()); } @GetMapping(value = "/authorization") public RedirectView authorization(HttpServletRequest servletReq) throws InterruptedException, ExecutionException, IOException { - OAuth10aService twitterService = createTwitterService(); + OAuth10aService twitterService = createService(); OAuth1RequestToken requestToken = twitterService.getRequestToken(); String authorizationUrl = twitterService.getAuthorizationUrl(requestToken); @@ -42,7 +42,7 @@ public class ScribeController { @GetMapping(value = "/callback", produces = "text/plain") @ResponseBody public String callback(HttpServletRequest servletReq, @RequestParam("oauth_verifier") String oauthV) throws InterruptedException, ExecutionException, IOException { - OAuth10aService twitterService = createTwitterService(); + OAuth10aService twitterService = createService(); OAuth1RequestToken requestToken = (OAuth1RequestToken) servletReq.getSession().getAttribute("requestToken"); OAuth1AccessToken accessToken = twitterService.getAccessToken(requestToken, oauthV); diff --git a/spring-mvc-simple/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java b/spring-mvc-simple/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java new file mode 100644 index 0000000000..fe7aeeb570 --- /dev/null +++ b/spring-mvc-simple/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java @@ -0,0 +1,45 @@ +package com.baeldung.controller.rss; + +import com.baeldung.spring.configuration.ApplicationConfiguration; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringJUnitWebConfig(ApplicationConfiguration.class) +public class ArticleRssIntegrationTest { + public static final String APPLICATION_RSS_XML = "application/rss+xml"; + public static final String APPLICATION_RSS_JSON = "application/rss+json"; + public static final String APPLICATION_RSS_XML_CHARSET_UTF_8 = "application/rss+xml;charset=UTF-8"; + + @Autowired + private WebApplicationContext webAppContext; + private MockMvc mockMvc; + + @BeforeEach + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext) + .build(); + } + + @Test + public void whenRequestingXMLFeed_thenContentTypeIsOk() throws Exception { + mockMvc.perform(get("/rss2").accept(APPLICATION_RSS_XML)) + .andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_RSS_XML_CHARSET_UTF_8)); + } + + @Test + public void whenRequestingJSONFeed_thenContentTypeIsOk() throws Exception { + mockMvc.perform(get("/rss2").accept(APPLICATION_RSS_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_RSS_JSON)); + } +} \ No newline at end of file diff --git a/testing-modules/mockito/pom.xml b/testing-modules/mockito/pom.xml index 1ec1ffe7bd..cdd73e6efe 100644 --- a/testing-modules/mockito/pom.xml +++ b/testing-modules/mockito/pom.xml @@ -46,14 +46,14 @@ ${powermock.version} test - + org.hamcrest java-hamcrest - 2.0.0.0 + ${hamcrest.version} test - + @@ -74,6 +74,7 @@ 1.7.0 + 2.0.0.0 diff --git a/testing-modules/mockito/src/test/java/org/baeldung/hamcrest/HamcrestNumberUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/hamcrest/HamcrestNumberUnitTest.java index 21606afd79..fbba6b94d2 100644 --- a/testing-modules/mockito/src/test/java/org/baeldung/hamcrest/HamcrestNumberUnitTest.java +++ b/testing-modules/mockito/src/test/java/org/baeldung/hamcrest/HamcrestNumberUnitTest.java @@ -6,8 +6,15 @@ import java.math.BigDecimal; import java.time.LocalDate; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.closeTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.comparesEqualTo; +import static org.hamcrest.Matchers.notANumber; public class HamcrestNumberUnitTest { @@ -43,6 +50,19 @@ public class HamcrestNumberUnitTest { assertThat(actual, is(not(closeTo(operand, error)))); } + @Test + public void given5_whenComparesEqualTo5_thenCorrect() { + Integer five = 5; + assertThat(five, comparesEqualTo(five)); + } + + @Test + public void given5_whenNotComparesEqualTo7_thenCorrect() { + Integer seven = 7; + Integer five = 5; + assertThat(five, not(comparesEqualTo(seven))); + } + @Test public void given7_whenGreaterThan5_thenCorrect() { Integer seven = 7; @@ -149,4 +169,10 @@ public class HamcrestNumberUnitTest { else return -1; } } + + @Test + public void givenNaN_whenIsNotANumber_thenCorrect() { + double zero = 0d; + assertThat(zero / zero, is(notANumber())); + } } diff --git a/testing-modules/testing/README.md b/testing-modules/testing/README.md index 2894da3496..c9c656dde9 100644 --- a/testing-modules/testing/README.md +++ b/testing-modules/testing/README.md @@ -18,3 +18,4 @@ - [Custom JUnit 4 Test Runners](http://www.baeldung.com/junit-4-custom-runners) - [Guide to JSpec](http://www.baeldung.com/jspec) - [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion) +- [Using Conditions with AssertJ](http://www.baeldung.com/assertj-conditions)