diff --git a/core-java-modules/core-java-11/pom.xml b/core-java-modules/core-java-11/pom.xml index b78c141552..4d950bdf8d 100644 --- a/core-java-modules/core-java-11/pom.xml +++ b/core-java-modules/core-java-11/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 com.baeldung core-java-11 @@ -12,7 +14,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../../ + ../.. @@ -21,6 +23,12 @@ guava ${guava.version} + + org.assertj + assertj-core + ${assertj.version} + test + @@ -41,6 +49,7 @@ 11 11 27.1-jre + 3.11.1 diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java new file mode 100644 index 0000000000..3c93e08194 --- /dev/null +++ b/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java @@ -0,0 +1,19 @@ +package com.baeldung.predicate.not; + +public class Person { + private static final int ADULT_AGE = 18; + + private int age; + + public Person(int age) { + this.age = age; + } + + public boolean isAdult() { + return age >= ADULT_AGE; + } + + public boolean isNotAdult() { + return !isAdult(); + } +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/AppTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java similarity index 82% rename from core-java-modules/core-java-11/src/test/java/com/baeldung/AppTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java index c9f61455bd..73eb8e661a 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/AppTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java @@ -7,7 +7,7 @@ import junit.framework.TestSuite; /** * Unit test for simple App. */ -public class AppTest +public class AppUnitTest extends TestCase { /** @@ -15,7 +15,7 @@ public class AppTest * * @param testName name of the test case */ - public AppTest( String testName ) + public AppUnitTest(String testName ) { super( testName ); } @@ -25,7 +25,7 @@ public class AppTest */ public static Test suite() { - return new TestSuite( AppTest.class ); + return new TestSuite( AppUnitTest.class ); } /** diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java similarity index 99% rename from core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java index 0e9c12675c..42f56838c4 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java @@ -32,7 +32,7 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; -public class HttpClientTest { +public class HttpClientUnitTest { @Test public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException { diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java similarity index 99% rename from core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java index 274d3a93fc..b87e6b3c6e 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java @@ -19,7 +19,7 @@ import java.time.Duration; import org.junit.Test; -public class HttpRequestTest { +public class HttpRequestUnitTest { @Test public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java similarity index 98% rename from core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java index abbc0233c1..a5cfc3f6b1 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java @@ -14,7 +14,7 @@ import java.net.http.HttpResponse; import org.junit.Test; -public class HttpResponseTest { +public class HttpResponseUnitTest { @Test public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java new file mode 100644 index 0000000000..a4989287be --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.predicate.not; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.function.Predicate.not; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class PersonUnitTest { + private List people; + + @BeforeEach + void preparePeople() { + people = Arrays.asList( + new Person(1), + new Person(18), + new Person(2) + ); + } + + @Test + void givenPeople_whenFilterIsAdult_thenOneResult() { + List adults = people.stream() + .filter(Person::isAdult) + .collect(Collectors.toList()); + + assertThat(adults).size().isEqualTo(1); + } + + @Test + void givenPeople_whenFilterIsAdultNegated_thenTwoResults() { + List nonAdults = people.stream() + .filter(person -> !person.isAdult()) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } + + @Test + void givenPeople_whenFilterIsNotAdult_thenTwoResults() { + List nonAdults = people.stream() + .filter(Person::isNotAdult) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } + + @Test + void givenPeople_whenFilterNotIsAdult_thenTwoResults() { + List nonAdults = people.stream() + .filter(not(Person::isAdult)) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java new file mode 100644 index 0000000000..3d80a36bf6 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java @@ -0,0 +1,43 @@ +package com.baeldung.string; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Test; + +public class StringAPITest { + + @Test + public void whenPositiveArgument_thenReturnIndentedString() { + String multilineStr = "This is\na multiline\nstring."; + String outputStr = " This is\n a multiline\n string.\n"; + + String postIndent = multilineStr.indent(3); + + assertThat(postIndent, equalTo(outputStr)); + } + + @Test + public void whenNegativeArgument_thenReturnReducedIndentedString() { + String multilineStr = " This is\n a multiline\n string."; + String outputStr = " This is\n a multiline\n string.\n"; + + String postIndent = multilineStr.indent(-2); + + assertThat(postIndent, equalTo(outputStr)); + } + + @Test + public void whenTransformUsingLamda_thenReturnTransformedString() { + String result = "hello".transform(input -> input + " world!"); + + assertThat(result, equalTo("hello world!")); + } + + @Test + public void whenTransformUsingParseInt_thenReturnInt() { + int result = "42".transform(Integer::parseInt); + + assertThat(result, equalTo(42)); + } +} diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/delay/Delay.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/delay/Delay.java new file mode 100644 index 0000000000..0cc0c9487f --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/delay/Delay.java @@ -0,0 +1,91 @@ +package com.baeldung.delay; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class Delay { + + public static void main(String args[]) throws InterruptedException { + + threadSleep(4, 1); + + timeunitSleep(4, 1); + + delayedServiceTask(5); + + fixedRateServiceTask(5); + + System.out.println("Done."); + + return; + + } + + private static void threadSleep(Integer iterations, Integer secondsToSleep) { + + for (Integer i = 0; i < iterations; i++) { + + System.out.println("This is loop iteration number " + i.toString()); + + try { + Thread.sleep(secondsToSleep * 1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + } + + } + + private static void timeunitSleep(Integer iterations, Integer secondsToSleep) { + + for (Integer i = 0; i < iterations; i++) { + + System.out.println("This is loop iteration number " + i.toString()); + + try { + TimeUnit.SECONDS.sleep(secondsToSleep); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + } + + } + + private static void delayedServiceTask(Integer delayInSeconds) { + + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + executorService.schedule(Delay::someTask1, delayInSeconds, TimeUnit.SECONDS); + + } + + private static void fixedRateServiceTask(Integer delayInSeconds) { + + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + ScheduledFuture sf = executorService.scheduleAtFixedRate(Delay::someTask2, 0, delayInSeconds, + TimeUnit.SECONDS); + + try { + TimeUnit.SECONDS.sleep(20); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + sf.cancel(true); + + } + + private static void someTask1() { + System.out.println("Task 1 completed."); + } + + private static void someTask2() { + System.out.println("Task 2 completed."); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-array-list/README.md b/core-java-modules/core-java-collections-array-list/README.md new file mode 100644 index 0000000000..3d1cdd5085 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/README.md @@ -0,0 +1,10 @@ +========= + +## Core Java Collections Array List Cookbooks and Examples + +### Relevant Articles: +- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) +- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist) +- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list) +- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) +- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) \ No newline at end of file diff --git a/core-java-modules/core-java-collections-array-list/pom.xml b/core-java-modules/core-java-collections-array-list/pom.xml new file mode 100644 index 0000000000..95a5f3ea36 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + core-java-collections-array-list + 0.1.0-SNAPSHOT + core-java-collections-array-list + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + 4.1 + 3.8.1 + 3.11.1 + + diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/Flower.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/Flower.java new file mode 100644 index 0000000000..eb897ea72f --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/Flower.java @@ -0,0 +1,28 @@ +package com.baeldung.java.list; + +public class Flower { + + private String name; + private int petals; + + public Flower(String name, int petals) { + this.name = name; + this.petals = petals; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPetals() { + return petals; + } + + public void setPetals(int petals) { + this.petals = petals; + } +} diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ThreeDimensionalArrayList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ThreeDimensionalArrayList.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ThreeDimensionalArrayList.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ThreeDimensionalArrayList.java diff --git a/core-java-modules/core-java-collections-array-list/src/main/resources/logback.xml b/core-java-modules/core-java-collections-array-list/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java rename to core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java rename to core-java-modules/core-java-collections-array-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java rename to core-java-modules/core-java-collections-array-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java diff --git a/core-java-modules/core-java-collections-list-2/README.md b/core-java-modules/core-java-collections-list-2/README.md new file mode 100644 index 0000000000..be10a0210c --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/README.md @@ -0,0 +1,17 @@ +========= + +## Core Java Collections List Cookbooks and Examples + +### Relevant Articles: +- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality) +- [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items) +- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist) +- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception) +- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line) +- [Ways to Iterate Over a List in Java](https://www.baeldung.com/java-iterate-list) +- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) +- [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) +- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) +- [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) +- [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance) +- [Filtering a Java Collection by a List](https://www.baeldung.com/java-filter-collection-by-list) \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-2/pom.xml b/core-java-modules/core-java-collections-list-2/pom.xml new file mode 100644 index 0000000000..d200a3c90c --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + core-java-collections-list-2 + 0.1.0-SNAPSHOT + core-java-collections-list-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + net.sf.trove4j + trove4j + ${trove4j.version} + + + it.unimi.dsi + fastutil + ${fastutil.version} + + + colt + colt + ${colt.version} + + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + + + + + 4.1 + 3.8.1 + 3.11.1 + 3.0.2 + 8.1.0 + 1.2.0 + + diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/collection/filtering/Employee.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/collection/filtering/Employee.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/WaysToIterate.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/java/list/WaysToIterate.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/WaysToIterate.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/java/list/WaysToIterate.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java diff --git a/core-java-modules/core-java-collections-list-2/src/main/resources/logback.xml b/core-java-modules/core-java-collections-list-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListJUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListJUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListJUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListJUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java diff --git a/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/README.md b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/README.md similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/lists/README.md rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/README.md diff --git a/core-java-modules/core-java-collections-list/README.md b/core-java-modules/core-java-collections-list/README.md index bfe06581c0..4bc1c5fb57 100644 --- a/core-java-modules/core-java-collections-list/README.md +++ b/core-java-modules/core-java-collections-list/README.md @@ -3,31 +3,14 @@ ## Core Java Collections List Cookbooks and Examples ### Relevant Articles: -- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) -- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist) - [Java – Get Random Item/Element From a List](http://www.baeldung.com/java-random-list-element) - [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list) - [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list) - [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list) - [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards) -- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list) - [Remove the First Element from a List](http://www.baeldung.com/java-remove-first-element-from-list) - [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java) - [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) - [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max) - [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list) -- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list) -- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality) -- [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items) -- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist) -- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception) -- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line) -- [Ways to Iterate Over a List in Java](https://www.baeldung.com/java-iterate-list) -- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) -- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) -- [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) -- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) -- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) -- [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) -- [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance) -- [Filtering a Java Collection by a List](https://www.baeldung.com/java-filter-collection-by-list) +- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list) \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/pom.xml b/core-java-modules/core-java-collections-list/pom.xml index 1a0b1615c8..581505dc1e 100644 --- a/core-java-modules/core-java-collections-list/pom.xml +++ b/core-java-modules/core-java-collections-list/pom.xml @@ -36,42 +36,12 @@ ${lombok.version} provided - - - net.sf.trove4j - trove4j - ${trove4j.version} - - - it.unimi.dsi - fastutil - ${fastutil.version} - - - colt - colt - ${colt.version} - - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-core.version} - 4.1 3.8.1 - 1.7.0 3.11.1 3.0.2 - 8.1.0 - 1.2.0 diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml new file mode 100644 index 0000000000..6a41ec0d1a --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + consumermodule + jar + 1.0 + + + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java new file mode 100644 index 0000000000..c4b5eed011 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.consumermodule; + +import com.baeldung.servicemodule.external.TextService; +import com.baeldung.servicemodule.external.TextServiceFactory; + +public class Application { + + public static void main(String args[]) { + TextService textService = TextServiceFactory.getTextService("lowercase"); + System.out.println(textService.processText("Hello from Baeldung!")); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..c02e6e6522 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.consumermodule { + requires com.baeldung.servicemodule; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml new file mode 100644 index 0000000000..282723e0a0 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + pom + + + servicemodule + consumermodule + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + + + UTF-8 + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml new file mode 100644 index 0000000000..1bda70f867 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.baeldung.servicemodule + servicemodule + jar + + + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java new file mode 100644 index 0000000000..2b9f0dce50 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java @@ -0,0 +1,7 @@ +package com.baeldung.servicemodule.external; + +public interface TextService { + + String processText(String text); + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java new file mode 100644 index 0000000000..4611bc1c8c --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java @@ -0,0 +1,14 @@ +package com.baeldung.servicemodule.external; + +import com.baeldung.servicemodule.internal.LowercaseTextService; +import com.baeldung.servicemodule.internal.UppercaseTextService; + +public class TextServiceFactory { + + private TextServiceFactory() {} + + public static TextService getTextService(String name) { + return name.equalsIgnoreCase("lowercase") ? new LowercaseTextService(): new UppercaseTextService(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java new file mode 100644 index 0000000000..e2d98f609e --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java @@ -0,0 +1,12 @@ +package com.baeldung.servicemodule.internal; + +import com.baeldung.servicemodule.external.TextService; + +public class LowercaseTextService implements TextService { + + @Override + public String processText(String text) { + return text.toLowerCase(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java new file mode 100644 index 0000000000..c94da2a8a5 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java @@ -0,0 +1,12 @@ +package com.baeldung.servicemodule.internal; + +import com.baeldung.servicemodule.external.TextService; + +public class UppercaseTextService implements TextService { + + @Override + public String processText(String text) { + return text.toUpperCase(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java new file mode 100644 index 0000000000..230b659aa9 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.servicemodule { + exports com.baeldung.servicemodule.external; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml new file mode 100644 index 0000000000..828fe7de6a --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml @@ -0,0 +1,38 @@ + + + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + 4.0.0 + + com.baeldung.consumermodule + consumermodule + 1.0 + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + com.baeldung.providermodule + providermodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java new file mode 100644 index 0000000000..b9430eb458 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java @@ -0,0 +1,15 @@ +package com.baeldung.consumermodule; + +import com.baeldung.servicemodule.TextService; + +import java.util.ServiceLoader; + +public class Application { + + public static void main(String[] args) { + ServiceLoader services = ServiceLoader.load(TextService.class); + for (final TextService service: services) { + System.out.println("The service " + service.getClass().getSimpleName() + " says: " + service.parseText("Hello from Baeldung!")); + } + } +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..d8438a7bbc --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.consumermodule { + requires com.baeldung.servicemodule; + uses com.baeldung.servicemodule.TextService; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml new file mode 100644 index 0000000000..f8c05d40b8 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + pom + + + servicemodule + providermodule + consumermodule + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml new file mode 100644 index 0000000000..ceeda9049c --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + com.baeldung.providermodule + providermodule + 1.0 + + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java new file mode 100644 index 0000000000..51e742e641 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java @@ -0,0 +1,10 @@ +package com.baeldung.providermodule; + +import com.baeldung.servicemodule.TextService; + +public class LowercaseTextService implements TextService { + @Override + public String parseText(String text) { + return text.toLowerCase(); + } +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..1223aa0121 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.providermodule { + requires com.baeldung.servicemodule; + provides com.baeldung.servicemodule.TextService with com.baeldung.providermodule.LowercaseTextService; +} \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml new file mode 100644 index 0000000000..4de3df8c01 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + >com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java new file mode 100644 index 0000000000..dedbd774ca --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java @@ -0,0 +1,6 @@ +package com.baeldung.servicemodule; + +public interface TextService { + + String parseText(String text); +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java new file mode 100644 index 0000000000..dbd70b944b --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.servicemodule { + exports com.baeldung.servicemodule; +} \ No newline at end of file diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java new file mode 100644 index 0000000000..db673d5d50 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java @@ -0,0 +1,15 @@ +package com.baeldung.ddd.order.doubledispatch; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; + +public class AmountBasedDiscountPolicy implements DiscountPolicy { + @Override + public double discount(Order order) { + if (order.totalCost() + .isGreaterThan(Money.of(CurrencyUnit.USD, 500.00))) { + return 0.10; + } else + return 0; + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java new file mode 100644 index 0000000000..7e3c5765c6 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch; + +public interface DiscountPolicy { + double discount(Order order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java new file mode 100644 index 0000000000..ac7d49fdeb --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java @@ -0,0 +1,8 @@ +package com.baeldung.ddd.order.doubledispatch; + +public class FlatDiscountPolicy implements DiscountPolicy { + @Override + public double discount(Order order) { + return 0.01; + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java new file mode 100644 index 0000000000..c2f763e14c --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java @@ -0,0 +1,29 @@ +package com.baeldung.ddd.order.doubledispatch; + +import java.math.RoundingMode; +import java.util.List; + +import org.joda.money.Money; + +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.OrderVisitor; +import com.baeldung.ddd.order.doubledispatch.visitor.Visitable; + +public class Order extends com.baeldung.ddd.order.Order implements Visitable { + public Order(List orderLines) { + super(orderLines); + } + + public Money totalCost(SpecialDiscountPolicy discountPolicy) { + return totalCost().multipliedBy(1 - applyDiscountPolicy(discountPolicy), RoundingMode.HALF_UP); + } + + protected double applyDiscountPolicy(SpecialDiscountPolicy discountPolicy) { + return discountPolicy.discount(this); + } + + @Override + public void accept(OrderVisitor visitor) { + visitor.visit(this); + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java new file mode 100644 index 0000000000..866e0e63c2 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch; + +public interface SpecialDiscountPolicy extends DiscountPolicy { + double discount(SpecialOrder order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java new file mode 100644 index 0000000000..1fe629e0ef --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java @@ -0,0 +1,36 @@ +package com.baeldung.ddd.order.doubledispatch; + +import java.util.List; + +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.OrderVisitor; + +public class SpecialOrder extends Order { + + private boolean eligibleForExtraDiscount; + + public SpecialOrder(List orderLines) { + super(orderLines); + this.eligibleForExtraDiscount = false; + } + + public SpecialOrder(List orderLines, boolean eligibleForSpecialDiscount) { + super(orderLines); + this.eligibleForExtraDiscount = eligibleForSpecialDiscount; + } + + public boolean isEligibleForExtraDiscount() { + return eligibleForExtraDiscount; + } + + @Override + protected double applyDiscountPolicy(SpecialDiscountPolicy discountPolicy) { + return discountPolicy.discount(this); + } + + @Override + public void accept(OrderVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java new file mode 100644 index 0000000000..ea23cdaa4b --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java @@ -0,0 +1,24 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public class HtmlOrderViewCreator implements OrderVisitor { + + private String html; + + public String getHtml() { + return html; + } + + @Override + public void visit(Order order) { + html = String.format("

Regular order total cost: %s

", order.totalCost()); + } + + @Override + public void visit(SpecialOrder order) { + html = String.format("

Special Order

total cost: %s

", order.totalCost()); + } + +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java new file mode 100644 index 0000000000..00f0740f6e --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java @@ -0,0 +1,9 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public interface OrderVisitor { + void visit(Order order); + void visit(SpecialOrder order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java new file mode 100644 index 0000000000..1628718d9b --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +public interface Visitable { + void accept(V visitor); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java index ed11b0dca4..81ae3bbd19 100644 --- a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java +++ b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java @@ -92,7 +92,7 @@ class JpaOrder { } void removeLineItem(int line) { - JpaOrderLine removedLine = orderLines.remove(line); + orderLines.remove(line); } void setCurrencyUnit(String currencyUnit) { diff --git a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java index 61e67fa12a..1d2ae5230a 100644 --- a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java +++ b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java @@ -15,7 +15,7 @@ class JpaProduct { public JpaProduct(BigDecimal price, String currencyUnit) { super(); this.price = price; - currencyUnit = currencyUnit; + this.currencyUnit = currencyUnit; } @Override diff --git a/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java b/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java new file mode 100644 index 0000000000..2b0e0b1997 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java @@ -0,0 +1,17 @@ +package com.baeldung.ddd.order; + +import java.util.Arrays; +import java.util.List; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; + +public class OrderFixtureUtils { + public static List anyOrderLines() { + return Arrays.asList(new OrderLine(new Product(Money.of(CurrencyUnit.USD, 100)), 1)); + } + + public static List orderLineItemsWorthNDollars(int totalCost) { + return Arrays.asList(new OrderLine(new Product(Money.of(CurrencyUnit.USD, totalCost)), 1)); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java new file mode 100644 index 0000000000..0ec73415d3 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.OrderFixtureUtils; + +public class DoubleDispatchDiscountPolicyUnitTest { + // @formatter:off + @DisplayName( + "given regular order with items worth $100 total, " + + "when apply 10% discount policy, " + + "then cost after discount is $90" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + Order order = new Order(OrderFixtureUtils.orderLineItemsWorthNDollars(100)); + SpecialDiscountPolicy discountPolicy = new SpecialDiscountPolicy() { + + @Override + public double discount(Order order) { + return 0.10; + } + + @Override + public double discount(SpecialOrder order) { + return 0; + } + }; + + // when + Money totalCostAfterDiscount = order.totalCost(discountPolicy); + + // then + assertThat(totalCostAfterDiscount).isEqualTo(Money.of(CurrencyUnit.USD, 90)); + } + + // @formatter:off + @DisplayName( + "given special order eligible for extra discount with items worth $100 total, " + + "when apply 20% discount policy for extra discount orders, " + + "then cost after discount is $80" + ) + // @formatter:on + @Test + void test1() throws Exception { + // given + boolean eligibleForExtraDiscount = true; + Order order = new SpecialOrder(OrderFixtureUtils.orderLineItemsWorthNDollars(100), eligibleForExtraDiscount); + SpecialDiscountPolicy discountPolicy = new SpecialDiscountPolicy() { + + @Override + public double discount(Order order) { + return 0; + } + + @Override + public double discount(SpecialOrder order) { + if (order.isEligibleForExtraDiscount()) + return 0.20; + return 0.10; + } + }; + + // when + Money totalCostAfterDiscount = order.totalCost(discountPolicy); + + // then + assertThat(totalCostAfterDiscount).isEqualTo(Money.of(CurrencyUnit.USD, 80.00)); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java new file mode 100644 index 0000000000..e360c1c76a --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.OrderFixtureUtils; +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.HtmlOrderViewCreator; + +public class HtmlOrderViewCreatorUnitTest { + // @formatter:off + @DisplayName( + "given collection of regular and special orders, " + + "when create HTML view using visitor for each order, " + + "then the dedicated view is created for each order" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + List anyOrderLines = OrderFixtureUtils.anyOrderLines(); + List orders = Arrays.asList(new Order(anyOrderLines), new SpecialOrder(anyOrderLines)); + HtmlOrderViewCreator htmlOrderViewCreator = new HtmlOrderViewCreator(); + + // when + orders.get(0) + .accept(htmlOrderViewCreator); + String regularOrderHtml = htmlOrderViewCreator.getHtml(); + orders.get(1) + .accept(htmlOrderViewCreator); + String specialOrderHtml = htmlOrderViewCreator.getHtml(); + + // then + assertThat(regularOrderHtml).containsPattern("

Regular order total cost: .*

"); + assertThat(specialOrderHtml).containsPattern("

Special Order

total cost: .*

"); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java new file mode 100644 index 0000000000..3d135e9dbe --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.OrderFixtureUtils; +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.SpecialDiscountPolicy; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public class MethodOverloadExampleUnitTest { +// @formatter:off +@DisplayName( + "given discount policy accepting special orders, " + + "when apply the policy on special order declared as regular order, " + + "then regular discount method is used" + ) +// @formatter:on + @Test + void test() throws Exception { + // given + SpecialDiscountPolicy specialPolicy = new SpecialDiscountPolicy() { + @Override + public double discount(Order order) { + return 0.01; + } + + @Override + public double discount(SpecialOrder order) { + return 0.10; + } + }; + Order specialOrder = new SpecialOrder(anyOrderLines()); + + // when + double discount = specialPolicy.discount(specialOrder); + + // then + assertThat(discount).isEqualTo(0.01); + } + + private List anyOrderLines() { + return OrderFixtureUtils.anyOrderLines(); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java new file mode 100644 index 0000000000..82e074d028 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.OrderFixtureUtils; + +public class SingleDispatchDiscountPolicyUnitTest { + // @formatter:off + @DisplayName( + "given two discount policies, " + + "when use these policies, " + + "then single dispatch chooses the implementation based on runtime type" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + DiscountPolicy flatPolicy = new FlatDiscountPolicy(); + DiscountPolicy amountPolicy = new AmountBasedDiscountPolicy(); + Order orderWorth501Dollars = orderWorthNDollars(501); + + // when + double flatDiscount = flatPolicy.discount(orderWorth501Dollars); + double amountDiscount = amountPolicy.discount(orderWorth501Dollars); + + // then + assertThat(flatDiscount).isEqualTo(0.01); + assertThat(amountDiscount).isEqualTo(0.1); + } + + private Order orderWorthNDollars(int totalCost) { + return new Order(OrderFixtureUtils.orderLineItemsWorthNDollars(totalCost)); + } +} diff --git a/guava-collections-set/README.md b/guava-collections-set/README.md index cfbe67c13e..c36d9e0b61 100644 --- a/guava-collections-set/README.md +++ b/guava-collections-set/README.md @@ -1,4 +1,8 @@ +# Guava -### Relevant Articles: +## Relevant Articles: +- [Guava – Sets](http://www.baeldung.com/guava-sets) +- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) +- [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) - [Guide to Guava Multiset](https://www.baeldung.com/guava-multiset) diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java similarity index 93% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java index 1d19423f7e..f474fcb17b 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java @@ -1,14 +1,9 @@ package org.baeldung.guava; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - import com.google.common.base.Function; +import java.util.*; + public class GuavaMapFromSet extends AbstractMap { private class SingleEntry implements Entry { diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java similarity index 99% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java index d80f047f5c..03f2d8f891 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java @@ -1,15 +1,14 @@ package org.baeldung.guava; -import static org.junit.Assert.assertTrue; +import com.google.common.base.Function; +import org.junit.Test; import java.util.Arrays; import java.util.Map; import java.util.Set; import java.util.TreeSet; -import org.junit.Test; - -import com.google.common.base.Function; +import static org.junit.Assert.assertTrue; public class GuavaMapFromSetUnitTest { diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java similarity index 97% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java index 6f3092d845..edefc61fc4 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java @@ -1,13 +1,12 @@ package org.baeldung.guava; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import org.junit.Test; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; +import org.junit.Test; + +import static org.junit.Assert.*; public class GuavaRangeSetUnitTest { @@ -122,6 +121,5 @@ public class GuavaRangeSetUnitTest { .add(Range.closed(0, 2)) .add(Range.closed(3, 5)) .add(Range.closed(5, 8)).build(); - } } diff --git a/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java new file mode 100644 index 0000000000..dfd90ad738 --- /dev/null +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java @@ -0,0 +1,131 @@ +package org.baeldung.guava; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class GuavaSetOperationsUnitTest { + + @Test + public void whenCalculatingUnionOfSets_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set union = Sets.union(first, second); + assertThat(union, containsInAnyOrder('a', 'b', 'c', 'd')); + } + + @Test + public void whenCalculatingCartesianProductOfSets_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b'); + final Set second = ImmutableSet.of('c', 'd'); + final Set> result = Sets.cartesianProduct(ImmutableList.of(first, second)); + + final Function, String> func = new Function, String>() { + @Override + public final String apply(final List input) { + return Joiner + .on(" ").join(input); + } + }; + + final Iterable joined = Iterables.transform(result, func); + assertThat(joined, containsInAnyOrder("a c", "a d", "b c", "b d")); + } + + @Test + public void whenCalculatingSetIntersection_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set intersection = Sets.intersection(first, second); + assertThat(intersection, containsInAnyOrder('b', 'c')); + } + + @Test + public void whenCalculatingSetSymmetricDifference_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set intersection = Sets.symmetricDifference(first, second); + assertThat(intersection, containsInAnyOrder('a', 'd')); + } + + @Test + public void whenCalculatingPowerSet_thenCorrect() { + final Set chars = ImmutableSet.of('a', 'b'); + final Set> result = Sets.powerSet(chars); + + final Set empty = ImmutableSet. builder().build(); + final Set a = ImmutableSet.of('a'); + final Set b = ImmutableSet.of('b'); + final Set aB = ImmutableSet.of('a', 'b'); + + assertThat(result, contains(empty, a, b, aB)); + } + + @Test + public void whenCreatingRangeOfIntegersSet_thenCreated() { + final int start = 10; + final int end = 30; + final ContiguousSet set = ContiguousSet.create(Range.closed(start, end), DiscreteDomain.integers()); + + assertEquals(21, set.size()); + assertEquals(10, set.first().intValue()); + assertEquals(30, set.last().intValue()); + } + + @Test + public void whenUsingRangeSet_thenCorrect() { + final RangeSet rangeSet = TreeRangeSet.create(); + rangeSet.add(Range.closed(1, 10)); + rangeSet.add(Range.closed(12, 15)); + + assertEquals(2, rangeSet.asRanges().size()); + + rangeSet.add(Range.closed(10, 12)); + assertTrue(rangeSet.encloses(Range.closed(1, 15))); + assertEquals(1, rangeSet.asRanges().size()); + } + + @Test + public void whenInsertDuplicatesInMultiSet_thenInserted() { + final Multiset names = HashMultiset.create(); + names.add("John"); + names.add("Adam", 3); + names.add("John"); + + assertEquals(2, names.count("John")); + names.remove("John"); + assertEquals(1, names.count("John")); + + assertEquals(3, names.count("Adam")); + names.remove("Adam", 2); + assertEquals(1, names.count("Adam")); + } + + @Test + public void whenGetTopOcurringElementsWithMultiSet_thenCorrect() { + final Multiset names = HashMultiset.create(); + names.add("John"); + names.add("Adam", 5); + names.add("Jane"); + names.add("Tom", 2); + + final Set sorted = Multisets.copyHighestCountFirst(names).elementSet(); + final List topTwo = Lists.newArrayList(sorted).subList(0, 2); + assertEquals(2, topTwo.size()); + assertEquals("Adam", topTwo.get(0)); + assertEquals("Tom", topTwo.get(1)); + } +} diff --git a/guava-collections/README.md b/guava-collections/README.md index fc9cf549c3..e919a98c2b 100644 --- a/guava-collections/README.md +++ b/guava-collections/README.md @@ -11,13 +11,10 @@ - [Filtering and Transforming Collections in Guava](http://www.baeldung.com/guava-filter-and-transform-a-collection) - [Guava – Join and Split Collections](http://www.baeldung.com/guava-joiner-and-splitter-tutorial) - [Guava – Lists](http://www.baeldung.com/guava-lists) -- [Guava – Sets](http://www.baeldung.com/guava-sets) - [Guava – Maps](http://www.baeldung.com/guava-maps) - [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap) -- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) - [Guide to Guava RangeMap](http://www.baeldung.com/guava-rangemap) - [Guide to Guava MinMaxPriorityQueue and EvictingQueue](http://www.baeldung.com/guava-minmax-priority-queue-and-evicting-queue) - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) -- [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) - [Guide to Guava Table](http://www.baeldung.com/guava-table) - [Guide to Guava ClassToInstanceMap](http://www.baeldung.com/guava-class-to-instance-map) \ No newline at end of file diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java b/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java index cb6ec7ef96..ab38afa5c4 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java +++ b/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java @@ -111,120 +111,6 @@ public class GuavaCollectionTypesUnitTest { assertThat(immutable, contains("John", "Adam", "Jane", "Tom")); } - // sets - - @Test - public void whenCalculateUnionOfSets_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set union = Sets.union(first, second); - assertThat(union, containsInAnyOrder('a', 'b', 'c', 'd')); - } - - @Test - public void whenCalculateSetsProduct_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b'); - final Set second = ImmutableSet.of('c', 'd'); - final Set> result = Sets.cartesianProduct(ImmutableList.of(first, second)); - - final Function, String> func = new Function, String>() { - @Override - public final String apply(final List input) { - return Joiner.on(" ").join(input); - } - }; - - final Iterable joined = Iterables.transform(result, func); - assertThat(joined, containsInAnyOrder("a c", "a d", "b c", "b d")); - } - - @Test - public void whenCalculatingSetIntersection_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set intersection = Sets.intersection(first, second); - assertThat(intersection, containsInAnyOrder('b', 'c')); - } - - @Test - public void whenCalculatingSetSymmetricDifference_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set intersection = Sets.symmetricDifference(first, second); - assertThat(intersection, containsInAnyOrder('a', 'd')); - } - - @Test - public void whenCalculatingPowerSet_thenCorrect() { - final Set chars = ImmutableSet.of('a', 'b'); - final Set> result = Sets.powerSet(chars); - - final Set empty = ImmutableSet. builder().build(); - final Set a = ImmutableSet.of('a'); - final Set b = ImmutableSet.of('b'); - final Set aB = ImmutableSet.of('a', 'b'); - - assertThat(result, contains(empty, a, b, aB)); - } - - @Test - public void whenCreateRangeOfIntegersSet_thenCreated() { - final int start = 10; - final int end = 30; - final ContiguousSet set = ContiguousSet.create(Range.closed(start, end), DiscreteDomain.integers()); - - assertEquals(21, set.size()); - assertEquals(10, set.first().intValue()); - assertEquals(30, set.last().intValue()); - } - - @Test - public void whenCreateRangeSet_thenCreated() { - final RangeSet rangeSet = TreeRangeSet.create(); - rangeSet.add(Range.closed(1, 10)); - rangeSet.add(Range.closed(12, 15)); - - assertEquals(2, rangeSet.asRanges().size()); - - rangeSet.add(Range.closed(10, 12)); - assertTrue(rangeSet.encloses(Range.closed(1, 15))); - assertEquals(1, rangeSet.asRanges().size()); - } - - @Test - public void whenInsertDuplicatesInMultiSet_thenInserted() { - final Multiset names = HashMultiset.create(); - names.add("John"); - names.add("Adam", 3); - names.add("John"); - - assertEquals(2, names.count("John")); - names.remove("John"); - assertEquals(1, names.count("John")); - - assertEquals(3, names.count("Adam")); - names.remove("Adam", 2); - assertEquals(1, names.count("Adam")); - } - - @Test - public void whenGetTopUsingMultiSet_thenCorrect() { - final Multiset names = HashMultiset.create(); - names.add("John"); - names.add("Adam", 5); - names.add("Jane"); - names.add("Tom", 2); - - final Set sorted = Multisets.copyHighestCountFirst(names).elementSet(); - final List topTwo = Lists.newArrayList(sorted).subList(0, 2); - assertEquals(2, topTwo.size()); - assertEquals("Adam", topTwo.get(0)); - assertEquals("Tom", topTwo.get(1)); - } - @Test public void whenCreateImmutableMap_thenCreated() { final Map salary = ImmutableMap. builder().put("John", 1000).put("Jane", 1500).put("Adam", 2000).put("Tom", 2000).build(); diff --git a/java-strings-2/README.MD b/java-strings-2/README.MD index edda92221d..85832fde37 100644 --- a/java-strings-2/README.MD +++ b/java-strings-2/README.MD @@ -2,3 +2,4 @@ - [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting) - [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring) +- [Removing Stopwords from a String in Java](https://www.baeldung.com/java-string-remove-stopwords) diff --git a/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java b/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java new file mode 100644 index 0000000000..50d9a2b058 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.initialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import org.junit.Test; + +public class StringInitializationUnitTest { + + private String fieldString; + + void printDeclaredOnlyString() { + String localVarString = null; + + System.out.println(localVarString); // compilation error + System.out.println(fieldString); + } + + @Test + public void givenDeclaredFeldStringAndNullString_thenCompareEquals() { + String localVarString = null; + + assertEquals(fieldString, localVarString); + } + + @Test + public void givenTwoStringsWithSameLiteral_thenCompareReferencesEquals() { + String literalOne = "Baeldung"; + String literalTwo = "Baeldung"; + + assertTrue(literalOne == literalTwo); + } + + @Test + public void givenTwoStringsUsingNew_thenCompareReferencesNotEquals() { + String newStringOne = new String("Baeldung"); + String newStringTwo = new String("Baeldung"); + + assertFalse(newStringOne == newStringTwo); + } + + @Test + public void givenEmptyLiteralStringsAndNewObject_thenCompareEquals() { + String emptyLiteral = ""; + String emptyNewString = new String(""); + + assertEquals(emptyLiteral, emptyNewString); + } + + @Test + public void givenEmptyStringObjects_thenCompareEquals() { + String emptyNewString = new String(""); + String emptyNewStringTwo = new String(); + + assertEquals(emptyNewString, emptyNewStringTwo); + } +} diff --git a/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java index b828296dca..60a647f32c 100644 --- a/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java +++ b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java @@ -10,6 +10,10 @@ import java.util.Map; import java.util.UUID; import javax.ejb.EJB; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.CDI; import javax.inject.Inject; import org.jboss.arquillian.container.test.api.Deployment; @@ -47,68 +51,31 @@ public class CarServiceIntegrationTest { @EJB private CarServiceEjbSingleton carServiceEjbSingleton; + + @Test + public void givenASingleton_whenGetBeanIsCalledTwice_thenTheSameInstanceIsReturned() { + CarServiceSingleton one = getBean(CarServiceSingleton.class); + CarServiceSingleton two = getBean(CarServiceSingleton.class); + assertTrue(one == two); + } + + @Test + public void givenAPojo_whenGetBeanIsCalledTwice_thenDifferentInstancesAreReturned() { + CarServiceBean one = getBean(CarServiceBean.class); + CarServiceBean two = getBean(CarServiceBean.class); + assertTrue(one != two); + } - private static Map idMap = new HashMap<>(); - - @Before - public void setUp() { - // populate idMap only on first run - if (idMap.isEmpty()) { - LOG.info("setUp::carServiceBean: {}", carServiceBean.getId()); - idMap.put("carServiceBeanId", carServiceBean.getId()); - - LOG.info("setUp::carServiceSingleton: {}", carServiceSingleton.getId()); - idMap.put("carServiceSingletonId", carServiceSingleton.getId()); - - LOG.info("setUp::carServiceEjbSingleton: {}", carServiceEjbSingleton.getId()); - idMap.put("carServiceEjbSingletonId", carServiceEjbSingleton.getId()); - } + @SuppressWarnings("unchecked") + private T getBean(Class beanClass) { + BeanManager bm = CDI.current().getBeanManager(); + Bean bean = (Bean) bm.getBeans(beanClass).iterator().next(); + CreationalContext ctx = bm.createCreationalContext(bean); + return (T) bm.getReference(bean, beanClass, ctx); } @Test - public void givenRun1_whenGetId_thenSingletonIdEqual() { - int testRun = 1; - - assertNotNull(carServiceBean); - assertNotNull(carServiceSingleton); - assertNotNull(carServiceEjbSingleton); - - UUID carServiceBeanId = carServiceBean.getId(); - assertEquals(idMap.get("carServiceBeanId"), carServiceBeanId); - LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId); - - UUID carServiceSingletonId = carServiceSingleton.getId(); - assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId); - LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId); - - UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId(); - assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId); - LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId); - } - - @Test - public void givenRun2_whenGetId_thenSingletonIdEqual() { - int testRun = 2; - - assertNotNull(carServiceBean); - assertNotNull(carServiceSingleton); - assertNotNull(carServiceEjbSingleton); - - UUID carServiceBeanId = carServiceBean.getId(); - assertNotEquals(idMap.get("carServiceBeanId"), carServiceBeanId); - LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId); - - UUID carServiceSingletonId = carServiceSingleton.getId(); - assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId); - LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId); - - UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId(); - assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId); - LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId); - } - - @Test - public void givenRun3_whenSingleton_thenNoLocking() { + public void givenCDI_whenConcurrentAccess_thenLockingIsNotProvided() { for (int i = 0; i < 10; i++) { new Thread(new Runnable() { @Override @@ -124,7 +91,7 @@ public class CarServiceIntegrationTest { } @Test - public void givenRun4_whenEjb_thenLocking() { + public void givenEJB_whenConcurrentAccess_thenLockingIsProvided() { for (int i = 0; i < 10; i++) { new Thread(new Runnable() { @Override diff --git a/kotlin-libraries-2/pom.xml b/kotlin-libraries-2/pom.xml index e2e261cb1b..14ac61a093 100644 --- a/kotlin-libraries-2/pom.xml +++ b/kotlin-libraries-2/pom.xml @@ -18,14 +18,16 @@ com.fasterxml.jackson.module jackson-module-kotlin + + io.reactivex.rxjava2 + rxkotlin + 2.3.0 + junit junit test - - - diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt new file mode 100644 index 0000000000..979ed3f809 --- /dev/null +++ b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt @@ -0,0 +1,157 @@ +package com.baeldung.kotlin.rxkotlin + +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.functions.BiFunction +import io.reactivex.rxkotlin.* +import io.reactivex.subjects.PublishSubject +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse + +class RxKotlinTest { + + @Test + fun whenBooleanArrayToObserver_thenBooleanObserver() { + val observable = listOf(true, false, false).toObservable() + observable.test().assertValues(true, false, false) + } + + @Test + fun whenBooleanArrayToFlowable_thenBooleanFlowable() { + val flowable = listOf(true, false, false).toFlowable() + flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) + } + + @Test + fun whenIntArrayToObserver_thenIntObserver() { + val observable = listOf(1, 1, 2, 3).toObservable() + observable.test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenIntArrayToFlowable_thenIntFlowable() { + val flowable = listOf(1, 1, 2, 3).toFlowable() + flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) + } + + @Test + fun whenObservablePairToMap_thenSingleNoDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMap() + assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) + } + + @Test + fun whenObservablePairToMap_thenSingleWithDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMultimap() + assertEquals( + mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), + map.blockingGet()) + } + + @Test + fun whenMergeAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.mergeAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenConcatAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.concatAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenSwitchLatest_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.switchLatest() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenMergeAllMaybes_thenObservable() { + val subject = PublishSubject.create>() + val observable = subject.mergeAllMaybes() + val testObserver = observable.test() + subject.onNext(Maybe.just(1)) + subject.onNext(Maybe.just(2)) + subject.onNext(Maybe.empty()) + testObserver.assertValues(1, 2) + subject.onNext(Maybe.error(Exception(""))) + subject.onNext(Maybe.just(3)) + testObserver.assertValues(1, 2).assertError(Exception::class.java) + } + + @Test + fun whenMerge_thenStream() { + val observables = mutableListOf(Observable.just("first", "second")) + val observable = observables.merge() + observables.add(Observable.just("third", "fourth")) + observables.add(Observable.error(Exception("e"))) + observables.add(Observable.just("fifth")) + + observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) + } + + @Test + fun whenMergeDelayError_thenStream() { + val observables = mutableListOf>(Observable.error(Exception("e1"))) + val observable = observables.mergeDelayError() + observables.add(Observable.just("1", "2")) + observables.add(Observable.error(Exception("e2"))) + observables.add(Observable.just("3")) + + observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) + } + + @Test + fun whenCast_thenUniformType() { + val observable = Observable.just(1, 1, 2, 3) + observable.cast().test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenOfType_thenFilter() { + val observable = Observable.just(1, "and", 2, "and") + observable.ofType().test().assertValues(1, 2) + } + + @Test + fun whenFunction_thenCompletable() { + var value = 0 + val completable = { value = 3 }.toCompletable() + assertFalse(completable.test().isCancelled) + assertEquals(3, value) + } + + @Test + fun whenHelper_thenMoreIdiomaticKotlin() { + val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } + zipWith.subscribeBy(onNext = { println(it) }) + val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } + zip.subscribeBy(onNext = { println(it) }) + val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) + zipOrig.subscribeBy(onNext = { println(it) }) + } +} diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle index afb92de49e..db23a438a0 100644 --- a/kotlin-libraries/build.gradle +++ b/kotlin-libraries/build.gradle @@ -54,9 +54,8 @@ dependencies { testCompile group: 'org.jetbrains.spek', name: 'spek-subject-extension', version: '1.1.5' testCompile group: 'org.jetbrains.spek', name: 'spek-junit-platform-engine', version: '1.1.5' implementation 'com.beust:klaxon:3.0.1' - implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0' - } + task runServer(type: JavaExec) { main = 'APIServer' classpath = sourceSets.main.runtimeClasspath diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java new file mode 100644 index 0000000000..531bae40c5 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java @@ -0,0 +1,75 @@ +package com.baeldung.jpa.entity; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; + +import com.baeldung.util.Gender; + +@Entity +@Table(name="STUDENT") +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + @Column(name = "STUDENT_NAME", length = 50, nullable = false, unique = false) + private String name; + @Transient + private Integer age; + @Temporal(TemporalType.DATE) + private Date birthDate; + @Enumerated(EnumType.STRING) + private Gender gender; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java new file mode 100644 index 0000000000..d534f44e14 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java @@ -0,0 +1,91 @@ +package com.baeldung.jpa.enums; + +import javax.persistence.*; + +@Entity +public class Article { + + @Id + private int id; + + private String title; + + @Enumerated(EnumType.ORDINAL) + private Status status; + + @Enumerated(EnumType.STRING) + private Type type; + + @Basic + private int priorityValue; + + @Transient + private Priority priority; + + private Category category; + + public Article() { + } + + @PostLoad + void fillTransient() { + if (priorityValue > 0) { + this.priority = Priority.of(priorityValue); + } + } + + @PrePersist + void fillPersistent() { + if (priority != null) { + this.priorityValue = priority.getPriority(); + } + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java new file mode 100644 index 0000000000..83b81da01e --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java @@ -0,0 +1,17 @@ +package com.baeldung.jpa.enums; + +import java.util.stream.Stream; + +public enum Category { + SPORT("S"), MUSIC("M"), TECHNOLOGY("T"); + + private String code; + + Category(String code) { + this.code = code; + } + + public String getCode() { + return code; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java new file mode 100644 index 0000000000..98960f1569 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java @@ -0,0 +1,28 @@ +package com.baeldung.jpa.enums; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.util.stream.Stream; + +@Converter(autoApply = true) +public class CategoryConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(Category category) { + if (category == null) { + return null; + } + return category.getCode(); + } + + @Override + public Category convertToEntityAttribute(final String code) { + if (code == null) { + return null; + } + + return Stream.of(Category.values()) + .filter(c -> c.getCode().equals(code)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java new file mode 100644 index 0000000000..42ee254303 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java @@ -0,0 +1,24 @@ +package com.baeldung.jpa.enums; + +import java.util.stream.Stream; + +public enum Priority { + LOW(100), MEDIUM(200), HIGH(300); + + private int priority; + + private Priority(int priority) { + this.priority = priority; + } + + public int getPriority() { + return priority; + } + + public static Priority of(int priority) { + return Stream.of(Priority.values()) + .filter(p -> p.getPriority() == priority) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java new file mode 100644 index 0000000000..80d5662c7a --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java @@ -0,0 +1,5 @@ +package com.baeldung.jpa.enums; + +public enum Status { + OPEN, REVIEW, APPROVED, REJECTED; +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java new file mode 100644 index 0000000000..80459fbd3c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java @@ -0,0 +1,5 @@ +package com.baeldung.jpa.enums; + +enum Type { + INTERNAL, EXTERNAL; +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/util/Gender.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/Gender.java new file mode 100644 index 0000000000..13f08d995c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/Gender.java @@ -0,0 +1,6 @@ +package com.baeldung.util; + +public enum Gender { + MALE, + FEMALE +} diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 21a757f490..9c5543bc3c 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -26,6 +26,8 @@ org.hibernate.jpa.HibernatePersistenceProvider com.baeldung.jpa.stringcast.Message + com.baeldung.jpa.enums.Article + com.baeldung.jpa.enums.CategoryConverter true @@ -145,5 +147,20 @@ - - + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.entity.Student + true + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java new file mode 100644 index 0000000000..fdaaba5439 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java @@ -0,0 +1,91 @@ +package com.baeldung.jpa.entity; + +import static org.junit.Assert.assertEquals; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.util.Gender; + +public class StudentEntityIntegrationTest { + + private EntityManagerFactory emf; + private EntityManager em; + + @Before + public void setup() { + emf = Persistence.createEntityManagerFactory("jpa-entity-definition"); + em = emf.createEntityManager(); + } + + @Test + public void persistStudentThenRetrieveTheDetails() { + Student student = createStudentWithRelevantDetails(); + persist(student); + clearThePersistenceContext(); + List students = getStudentsFromTable(); + checkAssertionsWith(students); + } + + @After + public void destroy() { + if (em != null) { + em.close(); + } + if (emf != null) { + emf.close(); + } + } + + private void clearThePersistenceContext() { + em.clear(); + } + + private void checkAssertionsWith(List students) { + assertEquals(1, students.size()); + Student john = students.get(0); + assertEquals(1L, john.getId().longValue()); + assertEquals(null, john.getAge()); + assertEquals("John", john.getName()); + } + + private List getStudentsFromTable() { + String selectQuery = "SELECT student FROM Student student"; + TypedQuery selectFromStudentTypedQuery = em.createQuery(selectQuery, Student.class); + List students = selectFromStudentTypedQuery.getResultList(); + return students; + } + + private void persist(Student student) { + em.getTransaction().begin(); + em.persist(student); + em.getTransaction().commit(); + } + + private Student createStudentWithRelevantDetails() { + Student student = new Student(); + student.setAge(20); // the 'age' field has been annotated with @Transient + student.setName("John"); + Date date = getDate(); + student.setBirthDate(date); + student.setGender(Gender.MALE); + return student; + } + + private Date getDate() { + LocalDate localDate = LocalDate.of(2008, 7, 20); + return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + } + +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java new file mode 100644 index 0000000000..82f3abc04d --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.jpa.enums; + +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ArticleUnitTest { + + private static EntityManager em; + private static EntityManagerFactory emFactory; + + @BeforeClass + public static void setup() { + Map properties = new HashMap(); + properties.put("hibernate.show_sql", "true"); + properties.put("hibernate.format_sql", "true"); + emFactory = Persistence.createEntityManagerFactory("jpa-h2", properties); + em = emFactory.createEntityManager(); + } + + @Test + public void shouldPersistStatusEnumOrdinalValue() { + // given + Article article = new Article(); + article.setId(1); + article.setTitle("ordinal title"); + article.setStatus(Status.OPEN); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 1); + + assertEquals(1, persistedArticle.getId()); + assertEquals("ordinal title", persistedArticle.getTitle()); + assertEquals(Status.OPEN, persistedArticle.getStatus()); + } + + @Test + public void shouldPersistTypeEnumStringValue() { + // given + Article article = new Article(); + article.setId(2); + article.setTitle("string title"); + article.setType(Type.EXTERNAL); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 2); + + assertEquals(2, persistedArticle.getId()); + assertEquals("string title", persistedArticle.getTitle()); + assertEquals(Type.EXTERNAL, persistedArticle.getType()); + } + + @Test + public void shouldPersistPriorityIntValue() { + // given + Article article = new Article(); + article.setId(3); + article.setTitle("callback title"); + article.setPriority(Priority.HIGH); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 3); + + assertEquals(3, persistedArticle.getId()); + assertEquals("callback title", persistedArticle.getTitle()); + assertEquals(Priority.HIGH, persistedArticle.getPriority()); + + } + + @Test + public void shouldPersistCategoryEnumConvertedValue() { + // given + Article article = new Article(); + article.setId(4); + article.setTitle("converted title"); + article.setCategory(Category.MUSIC); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 4); + + assertEquals(4, persistedArticle.getId()); + assertEquals("converted title", persistedArticle.getTitle()); + assertEquals(Category.MUSIC, persistedArticle.getCategory()); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java new file mode 100644 index 0000000000..bba8bd35c4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java @@ -0,0 +1,58 @@ +package com.baeldung.like.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Movie { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + private String title; + private String director; + private String rating; + private int duration; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java new file mode 100644 index 0000000000..241bdd3306 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java @@ -0,0 +1,41 @@ +package com.baeldung.like.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import com.baeldung.like.model.Movie; + +public interface MovieRepository extends CrudRepository { + + List findByTitleContaining(String title); + + List findByTitleLike(String title); + + List findByTitleContains(String title); + + List findByTitleIsContaining(String title); + + List findByRatingStartsWith(String rating); + + List findByDirectorEndsWith(String director); + + List findByTitleContainingIgnoreCase(String title); + + List findByRatingNotContaining(String rating); + + List findByDirectorNotLike(String director); + + @Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%") + List searchByTitleLike(@Param("title") String title); + + @Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%") + List searchByRatingStartsWith(String rating); + + //Escaping works in SpringBoot >= 2.4.1 + //@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}") + @Query("SELECT m FROM Movie m WHERE m.director LIKE %:#{[0]}") + List searchByDirectorEndsWith(String director); +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java new file mode 100644 index 0000000000..99d7080792 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java @@ -0,0 +1,88 @@ +package com.baeldung.like; + +import static org.junit.Assert.assertEquals; +import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.like.model.Movie; +import com.baeldung.like.repository.MovieRepository; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Sql(scripts = { "/test-movie-data.sql" }) +@Sql(scripts = "/test-movie-cleanup.sql", executionPhase = AFTER_TEST_METHOD) +public class MovieRepositoryIntegrationTest { + @Autowired + private MovieRepository movieRepository; + + @Test + public void givenPartialTitle_WhenFindByTitleContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleLike("%in%"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleIsContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleContains("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_WhenFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenFindByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialTitle_WhenFindByTitleContainingIgnoreCase_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContainingIgnoreCase("the"); + assertEquals(2, results.size()); + } + + @Test + public void givenPartialTitle_WhenSearchByTitleLike_ThenMoviesShouldReturn() { + List results = movieRepository.searchByTitleLike("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_SearchFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenSearchByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialRating_findByRatingNotContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingNotContaining("PG"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialDirector_WhenFindByDirectorNotLike_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorNotLike("An%"); + assertEquals(5, results.size()); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql new file mode 100644 index 0000000000..90aa15307c --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql @@ -0,0 +1 @@ +DELETE FROM Movie; \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql new file mode 100644 index 0000000000..37f8e4fe64 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql @@ -0,0 +1,7 @@ +INSERT INTO movie(id, title, director, rating, duration) VALUES(1, 'Godzilla: King of the Monsters', ' Michael Dougherty', 'PG-13', 132); +INSERT INTO movie(id, title, director, rating, duration) VALUES(2, 'Avengers: Endgame', 'Anthony Russo', 'PG-13', 181); +INSERT INTO movie(id, title, director, rating, duration) VALUES(3, 'Captain Marvel', 'Anna Boden', 'PG-13', 123); +INSERT INTO movie(id, title, director, rating, duration) VALUES(4, 'Dumbo', 'Tim Burton', 'PG', 112); +INSERT INTO movie(id, title, director, rating, duration) VALUES(5, 'Booksmart', 'Olivia Wilde', 'R', 102); +INSERT INTO movie(id, title, director, rating, duration) VALUES(6, 'Aladdin', 'Guy Ritchie', 'PG', 128); +INSERT INTO movie(id, title, director, rating, duration) VALUES(7, 'The Sun Is Also a Star', 'Ry Russo-Young', 'PG-13', 100); diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java index 8ff6799e31..3b9aa2cc18 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java @@ -9,6 +9,6 @@ public class MultipleDbApplication { public static void main(String[] args) { SpringApplication.run(MultipleDbApplication.class, args); } - + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java new file mode 100644 index 0000000000..a6f8f0829f --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java @@ -0,0 +1,71 @@ +package com.baeldung.multipledb; + +import java.util.HashMap; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * By default, the persistence-multiple-db.properties file is read for + * non auto configuration in PersistenceProductConfiguration. + *

+ * If we need to use persistence-multiple-db-boot.properties and auto configuration + * then uncomment the below @Configuration class and comment out PersistenceProductConfiguration. + */ +//@Configuration +@PropertySource({"classpath:persistence-multiple-db-boot.properties"}) +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.product", entityManagerFactoryRef = "productEntityManager", transactionManagerRef = "productTransactionManager") +@Profile("!tc") +public class PersistenceProductAutoConfiguration { + @Autowired + private Environment env; + + public PersistenceProductAutoConfiguration() { + super(); + } + + // + + @Bean + public LocalContainerEntityManagerFactoryBean productEntityManager() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(productDataSource()); + em.setPackagesToScan("com.baeldung.multipledb.model.product"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + final HashMap properties = new HashMap(); + properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); + em.setJpaPropertyMap(properties); + + return em; + } + + @Bean + @ConfigurationProperties(prefix="spring.second-datasource") + public DataSource productDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean + public PlatformTransactionManager productTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(productEntityManager().getObject()); + return transactionManager; + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java new file mode 100644 index 0000000000..e04a1621b2 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java @@ -0,0 +1,75 @@ +package com.baeldung.multipledb; + +import java.util.HashMap; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * By default, the persistence-multiple-db.properties file is read for + * non auto configuration in PersistenceUserConfiguration. + *

+ * If we need to use persistence-multiple-db-boot.properties and auto configuration + * then uncomment the below @Configuration class and comment out PersistenceUserConfiguration. + */ +//@Configuration +@PropertySource({"classpath:persistence-multiple-db-boot.properties"}) +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.user", entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager") +@Profile("!tc") +public class PersistenceUserAutoConfiguration { + @Autowired + private Environment env; + + public PersistenceUserAutoConfiguration() { + super(); + } + + // + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean userEntityManager() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(userDataSource()); + em.setPackagesToScan("com.baeldung.multipledb.model.user"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + final HashMap properties = new HashMap(); + properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); + em.setJpaPropertyMap(properties); + + return em; + } + + @Bean + @Primary + @ConfigurationProperties(prefix="spring.datasource") + public DataSource userDataSource() { + return DataSourceBuilder.create().build(); + } + + @Primary + @Bean + public PlatformTransactionManager userTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(userEntityManager().getObject()); + return transactionManager; + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties b/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties new file mode 100644 index 0000000000..ffca79b3f5 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties @@ -0,0 +1,11 @@ +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false + +spring.datasource.jdbcUrl=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS +spring.datasource.username=sa +spring.datasource.password=sa + +spring.second-datasource.jdbcUrl=jdbc:h2:mem:spring_jpa_product;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PRODUCTS +spring.second-datasource.username=sa +spring.second-datasource.password=sa diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java index bcc4103d08..6ba10a4d49 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java @@ -12,7 +12,6 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; diff --git a/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md index c656efaa3b..c408ff3c96 100644 --- a/persistence-modules/spring-persistence-simple/README.md +++ b/persistence-modules/spring-persistence-simple/README.md @@ -11,6 +11,7 @@ - [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) +- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) ### Eclipse Config diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml index 5f48b267b5..1afacab164 100644 --- a/persistence-modules/spring-persistence-simple/pom.xml +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -18,12 +18,6 @@ org.springframework spring-orm ${org.springframework.version} - - - commons-logging - commons-logging - - org.springframework diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java similarity index 93% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java index c454ab3b54..569971e311 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java @@ -1,11 +1,10 @@ -package org.baeldung.config; +package com.baeldung.config; import java.util.Properties; import javax.sql.DataSource; import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; -import org.baeldung.persistence.dao.IFooDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -24,15 +23,16 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import com.baeldung.persistence.dao.impl.FooDao; +import com.baeldung.hibernate.dao.FooDao; +import com.baeldung.jpa.dao.IFooDao; import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement -@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaRepositories(basePackages = { "com.baeldung.hibernate.dao" }, transactionManagerRef = "jpaTransactionManager") @EnableJpaAuditing @PropertySource({ "classpath:persistence-mysql.properties" }) -@ComponentScan({ "com.baeldung.persistence" }) +@ComponentScan({ "com.baeldung.persistence", "com.baeldung.hibernate.dao" }) public class PersistenceConfig { @Autowired diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java similarity index 93% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java index ec0d4bca3c..9fae34d99e 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.config; +package com.baeldung.config; import java.util.Properties; @@ -25,8 +25,8 @@ import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement @PropertySource({ "classpath:persistence-h2.properties" }) -@ComponentScan({ "org.baeldung.persistence" }) -@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") +@ComponentScan({ "com.baeldung.persistence","com.baeldung.jpa.dao" }) +@EnableJpaRepositories(basePackages = "com.baeldung.jpa.dao") public class PersistenceJPAConfig { @Autowired @@ -42,7 +42,7 @@ public class PersistenceJPAConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java similarity index 69% rename from persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java index 2d940527e1..67c10fe7fe 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java @@ -1,9 +1,9 @@ -package com.baeldung.persistence.dao.impl; +package com.baeldung.hibernate.dao; -import org.baeldung.persistence.dao.IFooDao; -import org.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Foo; import org.springframework.stereotype.Repository; +import com.baeldung.jpa.dao.IFooDao; import com.baeldung.persistence.dao.common.AbstractHibernateDao; @Repository diff --git a/spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java similarity index 88% rename from spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java index 8a02fe6a53..48ddfb04b1 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.SQLException; @@ -10,7 +10,7 @@ public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTransl @Override protected DataAccessException customTranslate(final String task, final String sql, final SQLException sqlException) { - if (sqlException.getErrorCode() == -104) { + if (sqlException.getErrorCode() == 23505) { return new DuplicateKeyException("Custome Exception translator - Integrity contraint voilation.", sqlException); } return null; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/Employee.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java similarity index 96% rename from spring-all/src/main/java/org/baeldung/jdbc/Employee.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java index e9408eb7fa..a43eb265c7 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/Employee.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; public class Employee { private int id; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java similarity index 99% rename from spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index 1f0e7b28ad..9ba4ebdb6d 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.PreparedStatement; import java.sql.SQLException; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java similarity index 95% rename from spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java index f926836c40..d09cd45dbc 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java similarity index 84% rename from spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java index f7eb592366..ddc24e439f 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc.config; +package com.baeldung.jdbc.config; import javax.sql.DataSource; @@ -10,12 +10,12 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @Configuration -@ComponentScan("org.baeldung.jdbc") +@ComponentScan("com.baeldung.jdbc") public class SpringJdbcConfig { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build(); } // @Bean diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java similarity index 96% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java index decca35c08..4fbc8464bb 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.dao; +package com.baeldung.jpa.dao; import java.io.Serializable; import java.util.List; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java similarity index 73% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java index 77978c5cf2..e79a44a0c2 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java @@ -1,6 +1,6 @@ -package org.baeldung.persistence.dao; +package com.baeldung.jpa.dao; -import org.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Foo; import org.springframework.stereotype.Repository; @Repository diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java similarity index 74% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java index ba188b9b3a..8140c56edd 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java @@ -1,8 +1,8 @@ -package org.baeldung.persistence.dao; +package com.baeldung.jpa.dao; import java.util.List; -import org.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Foo; public interface IFooDao { diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java index 5bcebed761..d4da194f4d 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java @@ -2,11 +2,12 @@ package com.baeldung.persistence.dao.common; import java.io.Serializable; -import org.baeldung.persistence.dao.AbstractJpaDAO; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Repository; +import com.baeldung.jpa.dao.AbstractJpaDAO; + @Repository @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class GenericJpaDao extends AbstractJpaDAO implements IGenericDao { diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java similarity index 98% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java index b602e57562..5a88ecc6cf 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.model; +package com.baeldung.persistence.model; import java.io.Serializable; import java.util.List; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java similarity index 98% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java index 30635e9ef2..009876f8cb 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.model; +package com.baeldung.persistence.model; import java.io.Serializable; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java similarity index 81% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java index 6d1bb0adbe..efe9743670 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java @@ -1,9 +1,9 @@ -package org.baeldung.persistence.service; +package com.baeldung.persistence.service; import java.util.List; -import org.baeldung.persistence.dao.IFooDao; -import org.baeldung.persistence.model.Foo; +import com.baeldung.jpa.dao.IFooDao; +import com.baeldung.persistence.model.Foo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java similarity index 93% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java index 067bac2018..717b9c3aa0 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.config; +package com.baeldung.spring.data.persistence.config; import java.util.Properties; @@ -24,9 +24,9 @@ import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement @PropertySource({ "classpath:persistence-${envTarget:h2}.properties" }) -@ComponentScan({ "org.baeldung.spring.data.persistence" }) +@ComponentScan({ "com.baeldung.spring.data.persistence" }) // @ImportResource("classpath*:springDataPersistenceConfig.xml") -@EnableJpaRepositories(basePackages = "org.baeldung.spring.data.persistence.dao") +@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.dao") public class PersistenceConfig { @Autowired @@ -40,7 +40,7 @@ public class PersistenceConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.baeldung.spring.data.persistence.model" }); + em.setPackagesToScan(new String[] { "com.baeldung.spring.data.persistence.model" }); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); // vendorAdapter.set diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java similarity index 77% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java index 2f74096e14..d2b746dc8b 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java @@ -1,6 +1,6 @@ -package org.baeldung.spring.data.persistence.dao; +package com.baeldung.spring.data.persistence.dao; -import org.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.spring.data.persistence.model.Foo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java similarity index 97% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java index 4d01376af7..e8f95302ef 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java @@ -1,11 +1,11 @@ -package org.baeldung.spring.data.persistence.dao.user; +package com.baeldung.spring.data.persistence.dao.user; import java.time.LocalDate; import java.util.Collection; import java.util.List; import java.util.stream.Stream; -import org.baeldung.spring.data.persistence.model.User; +import com.baeldung.spring.data.persistence.model.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java similarity index 72% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java index 1a874fb5e5..ff92159077 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java @@ -1,11 +1,11 @@ -package org.baeldung.spring.data.persistence.dao.user; +package com.baeldung.spring.data.persistence.dao.user; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.function.Predicate; -import org.baeldung.spring.data.persistence.model.User; +import com.baeldung.spring.data.persistence.model.User; public interface UserRepositoryCustom { List findUserByEmails(Set emails); diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java similarity index 94% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java index c28050401c..8bd8217e83 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.dao.user; +package com.baeldung.spring.data.persistence.dao.user; import java.util.ArrayList; import java.util.Collection; @@ -15,7 +15,7 @@ import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import org.baeldung.spring.data.persistence.model.User; +import com.baeldung.spring.data.persistence.model.User; public class UserRepositoryCustomImpl implements UserRepositoryCustom { diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java similarity index 96% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java index 8f316ac55b..64bfe203d0 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.model; +package com.baeldung.spring.data.persistence.model; import java.io.Serializable; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java similarity index 97% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java index da64e78552..44ca9fc62e 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.model; +package com.baeldung.spring.data.persistence.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java similarity index 98% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java index 486ed046e5..09f1092644 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.model; +package com.baeldung.spring.data.persistence.model; import javax.persistence.*; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java similarity index 58% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java index 26d0171551..00e7ac01e4 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java @@ -1,6 +1,6 @@ -package org.baeldung.spring.data.persistence.service; +package com.baeldung.spring.data.persistence.service; -import org.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.spring.data.persistence.model.Foo; import com.baeldung.persistence.dao.common.IOperations; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java similarity index 95% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java index cf28d5e5c6..61c7d6fcaa 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.data.persistence.service.common; +package com.baeldung.spring.data.persistence.service.common; import java.io.Serializable; import java.util.List; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java similarity index 70% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java index b7ed496df1..cd566ba9f6 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java @@ -1,10 +1,10 @@ -package org.baeldung.spring.data.persistence.service.impl; +package com.baeldung.spring.data.persistence.service.impl; -import org.baeldung.spring.data.persistence.model.Foo; -import org.baeldung.spring.data.persistence.dao.IFooDao; -import org.baeldung.spring.data.persistence.service.IFooService; -import org.baeldung.spring.data.persistence.service.common.AbstractService; +import com.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.spring.data.persistence.dao.IFooDao; +import com.baeldung.spring.data.persistence.service.IFooService; +import com.baeldung.spring.data.persistence.service.common.AbstractService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Service; diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java similarity index 96% rename from persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java index 85ab623e5f..45e72e046d 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java @@ -1,4 +1,4 @@ -package org.baeldung.util; +package com.baeldung.util; import java.util.Random; diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql new file mode 100644 index 0000000000..c86d35cdae --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE EMPLOYEE +( + ID int NOT NULL PRIMARY KEY, + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + ADDRESS varchar(255), +); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml new file mode 100644 index 0000000000..e3d7452eb1 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql new file mode 100644 index 0000000000..b9ef8fec25 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql @@ -0,0 +1,7 @@ +INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada'); + +INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA'); + +INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland'); + +INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA'); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml index 6304fa0a65..57687c306d 100644 --- a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml @@ -11,7 +11,7 @@ - + - 2.21.0 + 2.22.0 3.7.0 1.6.0 1.8 @@ -1549,8 +1548,8 @@ 1.2 2.9.8 1.3 - 1.2.0 - 5.2.0 + 1.4.2 + 5.4.2 0.3.1 2.5.1 0.0.1 diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index 3306fd1729..c1f537d2fe 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -28,12 +28,22 @@ + + 1.8 + 2.2.0.M3 + + org.springframework.boot spring-boot-starter-webflux + + org.springframework.boot + spring-boot-starter-rsocket + + org.projectlombok lombok @@ -46,8 +56,8 @@ - junit - junit + io.projectreactor + reactor-test test @@ -60,4 +70,35 @@ + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java new file mode 100644 index 0000000000..6f35ec5ee0 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.rsocket.client; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class ClientApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder() + .main(ClientApplication.class) + .sources(ClientApplication.class) + .profiles("client") + .run(args); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java new file mode 100644 index 0000000000..7dd3591cd6 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.rsocket.client; + +import io.rsocket.RSocket; +import io.rsocket.RSocketFactory; +import io.rsocket.frame.decoder.PayloadDecoder; +import io.rsocket.transport.netty.client.TcpClientTransport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketStrategies; +import org.springframework.util.MimeTypeUtils; + +@Configuration +public class ClientConfiguration { + + @Bean + public RSocket rSocket() { + return RSocketFactory.connect() + .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE) + .frameDecoder(PayloadDecoder.ZERO_COPY) + .transport(TcpClientTransport.create(7000)) + .start() + .block(); + } + + @Bean + RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) { + return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java new file mode 100644 index 0000000000..3701bd69e9 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.rsocket.client; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import java.util.Random; +import org.reactivestreams.Publisher; +import org.springframework.http.MediaType; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MarketDataRestController { + + private final Random random = new Random(); + private final RSocketRequester rSocketRequester; + + public MarketDataRestController(RSocketRequester rSocketRequester) { + this.rSocketRequester = rSocketRequester; + } + + @GetMapping(value = "/current/{stock}") + public Publisher current(@PathVariable("stock") String stock) { + return rSocketRequester.route("currentMarketData") + .data(new MarketDataRequest(stock)) + .retrieveMono(MarketData.class); + } + + @GetMapping(value = "/feed/{stock}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Publisher feed(@PathVariable("stock") String stock) { + return rSocketRequester.route("feedMarketData") + .data(new MarketDataRequest(stock)) + .retrieveFlux(MarketData.class); + } + + @GetMapping(value = "/collect") + public Publisher collect() { + return rSocketRequester.route("collectMarketData") + .data(getMarketData()) + .send(); + } + + private MarketData getMarketData() { + return new MarketData("X", random.nextInt(10)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java new file mode 100644 index 0000000000..3eeaf449e9 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java @@ -0,0 +1,20 @@ +package com.baeldung.spring.rsocket.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MarketData { + + private String stock; + private int currentPrice; + + public static MarketData fromException(Exception e) { + MarketData marketData = new MarketData(); + marketData.setStock(e.getMessage()); + return marketData; + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java new file mode 100644 index 0000000000..1debbb0870 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.rsocket.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MarketDataRequest { + + private String stock; +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java new file mode 100644 index 0000000000..1ff23966fa --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java @@ -0,0 +1,40 @@ +package com.baeldung.spring.rsocket.server; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import org.springframework.messaging.handler.annotation.MessageExceptionHandler; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.stereotype.Controller; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Controller +public class MarketDataRSocketController { + + private final MarketDataRepository marketDataRepository; + + public MarketDataRSocketController(MarketDataRepository marketDataRepository) { + this.marketDataRepository = marketDataRepository; + } + + @MessageMapping("currentMarketData") + public Mono currentMarketData(MarketDataRequest marketDataRequest) { + return marketDataRepository.getOne(marketDataRequest.getStock()); + } + + @MessageMapping("feedMarketData") + public Flux feedMarketData(MarketDataRequest marketDataRequest) { + return marketDataRepository.getAll(marketDataRequest.getStock()); + } + + @MessageMapping("collectMarketData") + public Mono collectMarketData(MarketData marketData) { + marketDataRepository.add(marketData); + return Mono.empty(); + } + + @MessageExceptionHandler + public Mono handleException(Exception e) { + return Mono.just(MarketData.fromException(e)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java new file mode 100644 index 0000000000..4f30c36c2f --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java @@ -0,0 +1,37 @@ +package com.baeldung.spring.rsocket.server; + +import com.baeldung.spring.rsocket.model.MarketData; +import java.time.Duration; +import java.util.Random; +import java.util.stream.Stream; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Slf4j +@Component +public class MarketDataRepository { + + private static final int BOUND = 100; + + private Random random = new Random(); + + public Flux getAll(String stock) { + return Flux.fromStream(Stream.generate(() -> getMarketDataResponse(stock))) + .log() + .delayElements(Duration.ofSeconds(1)); + } + + public Mono getOne(String stock) { + return Mono.just(getMarketDataResponse(stock)); + } + + public void add(MarketData marketData) { + log.info("New market data: {}", marketData); + } + + private MarketData getMarketDataResponse(String stock) { + return new MarketData(stock, random.nextInt(BOUND)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java new file mode 100644 index 0000000000..4213e315dd --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.rsocket.server; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class ServerApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder() + .main(ServerApplication.class) + .sources(ServerApplication.class) + .profiles("server") + .run(args); + } +} diff --git a/spring-5-webflux/src/main/resources/application-client.properties b/spring-5-webflux/src/main/resources/application-client.properties new file mode 100644 index 0000000000..4c00e40deb --- /dev/null +++ b/spring-5-webflux/src/main/resources/application-client.properties @@ -0,0 +1 @@ +server.port=8080 diff --git a/spring-5-webflux/src/main/resources/application-server.properties b/spring-5-webflux/src/main/resources/application-server.properties new file mode 100644 index 0000000000..1e343b5bf5 --- /dev/null +++ b/spring-5-webflux/src/main/resources/application-server.properties @@ -0,0 +1,2 @@ +spring.rsocket.server.port=7000 +server.port=8081 diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java new file mode 100644 index 0000000000..ff00d5ec24 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java @@ -0,0 +1,92 @@ +package com.baeldung.spring.rsocket.client; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.http.MediaType.TEXT_EVENT_STREAM; + +import com.baeldung.spring.rsocket.model.MarketData; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketRequester.RequestSpec; +import org.springframework.messaging.rsocket.RSocketRequester.ResponseSpec; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.FluxExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +@RunWith(SpringRunner.class) +@WebFluxTest(value = MarketDataRestController.class) +public class MarketDataRestControllerIntegrationTest { + + @Autowired + private WebTestClient testClient; + + @MockBean + private RSocketRequester rSocketRequester; + + @Mock + private RequestSpec requestSpec; + + @Mock + private ResponseSpec responseSpec; + + @Test + public void whenInitiatesRequest_ThenGetsResponse() throws Exception { + when(rSocketRequester.route("currentMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + MarketData marketData = new MarketData("X", 1); + when(responseSpec.retrieveMono(MarketData.class)).thenReturn(Mono.just(marketData)); + + testClient.get() + .uri("/current/{stock}", "X") + .exchange() + .expectStatus() + .isOk() + .expectBody(MarketData.class) + .isEqualTo(marketData); + } + + @Test + public void whenInitiatesFireAndForget_ThenGetsNoResponse() throws Exception { + when(rSocketRequester.route("collectMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + when(responseSpec.send()).thenReturn(Mono.empty()); + + testClient.get() + .uri("/collect") + .exchange() + .expectStatus() + .isOk() + .expectBody(Void.class); + } + + @Test + public void whenInitiatesRequest_ThenGetsStream() throws Exception { + when(rSocketRequester.route("feedMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + MarketData firstMarketData = new MarketData("X", 1); + MarketData secondMarketData = new MarketData("X", 2); + when(responseSpec.retrieveFlux(MarketData.class)).thenReturn(Flux.just(firstMarketData, secondMarketData)); + + FluxExchangeResult result = testClient.get() + .uri("/feed/{stock}", "X") + .accept(TEXT_EVENT_STREAM) + .exchange() + .expectStatus() + .isOk() + .returnResult(MarketData.class); + Flux marketDataFlux = result.getResponseBody(); + StepVerifier.create(marketDataFlux) + .expectNext(firstMarketData) + .expectNext(secondMarketData) + .thenCancel() + .verify(); + } +} \ No newline at end of file diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java new file mode 100644 index 0000000000..dcf3b82730 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java @@ -0,0 +1,98 @@ +package com.baeldung.spring.rsocket.server; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import io.rsocket.RSocket; +import io.rsocket.RSocketFactory; +import io.rsocket.frame.decoder.PayloadDecoder; +import io.rsocket.transport.netty.client.TcpClientTransport; +import java.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketStrategies; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.MimeTypeUtils; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = {"spring.rsocket.server.port=7000"}) +public class MarketDataRSocketControllerLiveTest { + + @Autowired + private RSocketRequester rSocketRequester; + + @SpyBean + private MarketDataRSocketController rSocketController; + + @Test + public void whenGetsFireAndForget_ThenReturnsNoResponse() throws InterruptedException { + final MarketData marketData = new MarketData("X", 1); + rSocketRequester.route("collectMarketData") + .data(marketData) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).collectMarketData(any()); + } + + @Test + public void whenGetsRequest_ThenReturnsResponse() throws InterruptedException { + final MarketDataRequest marketDataRequest = new MarketDataRequest("X"); + rSocketRequester.route("currentMarketData") + .data(marketDataRequest) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).currentMarketData(any()); + } + + @Test + public void whenGetsRequest_ThenReturnsStream() throws InterruptedException { + final MarketDataRequest marketDataRequest = new MarketDataRequest("X"); + rSocketRequester.route("feedMarketData") + .data(marketDataRequest) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).feedMarketData(any()); + } + + private void sleepForProcessing() throws InterruptedException { + Thread.sleep(1000); + } + + @TestConfiguration + public static class ClientConfiguration { + + @Bean + @Lazy + public RSocket rSocket() { + return RSocketFactory.connect() + .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE) + .frameDecoder(PayloadDecoder.ZERO_COPY) + .transport(TcpClientTransport.create(7000)) + .start() + .block(); + } + + @Bean + @Lazy + RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) { + return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies); + } + } +} \ No newline at end of file diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java index 8919daa9fb..353cb24d0a 100644 --- a/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java @@ -1,5 +1,10 @@ package com.baeldung.spring.webclientrequests; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.time.Duration; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -17,8 +22,6 @@ import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.DefaultUriBuilderFactory; import reactor.core.publisher.Mono; -import static org.mockito.Mockito.*; - @RunWith(SpringRunner.class) @WebFluxTest public class WebClientRequestsUnitTest { @@ -50,7 +53,8 @@ public class WebClientRequestsUnitTest { public void whenCallSimpleURI_thenURIMatched() { this.webClient.get() .uri("/products") - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products"); } @@ -60,7 +64,8 @@ public class WebClientRequestsUnitTest { .uri(uriBuilder -> uriBuilder .path("/products/{id}") .build(2)) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/2"); } @@ -70,7 +75,8 @@ public class WebClientRequestsUnitTest { .uri(uriBuilder -> uriBuilder .path("/products/{id}/attributes/{attributeId}") .build(2, 13)) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/2/attributes/13"); } @@ -83,7 +89,8 @@ public class WebClientRequestsUnitTest { .queryParam("color", "black") .queryParam("deliveryDate", "13/04/2019") .build()) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13/04/2019"); } @@ -96,7 +103,8 @@ public class WebClientRequestsUnitTest { .queryParam("color", "{authorId}") .queryParam("deliveryDate", "{date}") .build("AndroidPhone", "black", "13/04/2019")) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13%2F04%2F2019"); } @@ -107,7 +115,8 @@ public class WebClientRequestsUnitTest { .path("/products/") .queryParam("tag[]", "Snapdragon", "NFC") .build()) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?tag%5B%5D=Snapdragon&tag%5B%5D=NFC"); } @@ -119,7 +128,8 @@ public class WebClientRequestsUnitTest { .path("/products/") .queryParam("category", "Phones", "Tablets") .build()) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?category=Phones&category=Tablets"); } @@ -130,7 +140,8 @@ public class WebClientRequestsUnitTest { .path("/products/") .queryParam("category", String.join(",", "Phones", "Tablets")) .build()) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?category=Phones,Tablets"); } @@ -151,7 +162,8 @@ public class WebClientRequestsUnitTest { .queryParam("color", "black") .queryParam("deliveryDate", "13/04/2019") .build()) - .retrieve(); + .exchange() + .block(Duration.ofSeconds(1)); verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13/04/2019"); } diff --git a/spring-all/README.md b/spring-all/README.md index b0805e5477..b5e91d8d60 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -33,5 +33,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring @Primary Annotation](http://www.baeldung.com/spring-primary) - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) -- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) diff --git a/spring-cloud/spring-cloud-contract/pom.xml b/spring-cloud/spring-cloud-contract/pom.xml index 4d4e8ad2c3..ea71891648 100644 --- a/spring-cloud/spring-cloud-contract/pom.xml +++ b/spring-cloud/spring-cloud-contract/pom.xml @@ -19,4 +19,45 @@ spring-cloud-contract-consumer + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-data-rest + ${spring-boot.version} + + + + org.springframework.cloud + spring-cloud-contract-wiremock + ${spring-cloud.version} + test + + + org.springframework.cloud + spring-cloud-contract-stub-runner + ${spring-cloud.version} + test + + + org.springframework.cloud + spring-cloud-starter-contract-verifier + ${spring-cloud.version} + test + + + + + + UTF-8 + UTF-8 + 1.8 + 2.1.1.RELEASE + 2.1.4.RELEASE + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml index afd045189c..3b711c58d9 100644 --- a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml +++ b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml @@ -20,37 +20,27 @@ org.springframework.cloud spring-cloud-contract-wiremock - ${spring-cloud.version} test org.springframework.cloud spring-cloud-contract-stub-runner - ${spring-cloud.version} test org.springframework.boot spring-boot-starter-web - ${spring-boot.version} org.springframework.boot spring-boot-starter-data-rest - ${spring-boot.version} com.baeldung.spring.cloud spring-cloud-contract-producer - 1.0.0-SNAPSHOT + ${project.parent.version} test - - UTF-8 - UTF-8 - 1.2.2.RELEASE - 1.5.9.RELEASE - diff --git a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/src/test/java/com/baeldung/spring/cloud/springcloudcontractconsumer/controller/BasicMathControllerIntegrationTest.java b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/src/test/java/com/baeldung/spring/cloud/springcloudcontractconsumer/controller/BasicMathControllerIntegrationTest.java index 5cf5c6d3b8..e21223e6ea 100644 --- a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/src/test/java/com/baeldung/spring/cloud/springcloudcontractconsumer/controller/BasicMathControllerIntegrationTest.java +++ b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/src/test/java/com/baeldung/spring/cloud/springcloudcontractconsumer/controller/BasicMathControllerIntegrationTest.java @@ -7,6 +7,7 @@ import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @@ -19,7 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureMockMvc @AutoConfigureJsonTesters -@AutoConfigureStubRunner(workOffline = true, +@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.baeldung.spring.cloud:spring-cloud-contract-producer:+:stubs:8090") public class BasicMathControllerIntegrationTest { diff --git a/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml b/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml index 07429687c7..dffbd29206 100644 --- a/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml +++ b/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml @@ -25,12 +25,10 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot.version} org.springframework.boot spring-boot-starter-data-rest - ${spring-boot.version} @@ -38,7 +36,7 @@ org.springframework.cloud spring-cloud-contract-maven-plugin - 1.2.2.RELEASE + 2.1.1.RELEASE true com.baeldung.spring.cloud.springcloudcontractproducer.BaseTestClass @@ -47,25 +45,4 @@ - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - - - UTF-8 - UTF-8 - Edgware.SR1 - 1.5.9.RELEASE - - diff --git a/spring-security-rest-custom/pom.xml b/spring-security-rest-custom/pom.xml index 8fdcb509ee..38cbfddab8 100644 --- a/spring-security-rest-custom/pom.xml +++ b/spring-security-rest-custom/pom.xml @@ -8,10 +8,10 @@ war - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java index 0c2042f711..d7b2da6fe7 100644 --- a/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java +++ b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java @@ -9,14 +9,14 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc @ComponentScan("org.baeldung.web") // @ImportResource({ "classpath:prop.xml" }) // @PropertySource("classpath:foo.properties") -public class WebConfig extends WebMvcConfigurerAdapter { +public class WebConfig implements WebMvcConfigurer { public WebConfig() { super(); @@ -26,7 +26,6 @@ public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(final List> converters) { - super.configureMessageConverters(converters); converters.add(new MappingJackson2HttpMessageConverter()); } diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index 84e0577cfe..b3074635a7 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -139,7 +139,7 @@ 5.4.2 2.8.2 2.0.0-RC.1 - 2.21.0 + 2.22.0 1.6.0 5.0.1.RELEASE diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java new file mode 100644 index 0000000000..db37e9a6d2 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.extension.RegisterExtension; +import com.baeldung.extensions.EmployeeDatabaseSetupExtension; + +public class MultipleExtensionsUnitTest { + + @Order(1) + @RegisterExtension + static EmployeeDatabaseSetupExtension SECOND_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbTwo;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @Order(0) + @RegisterExtension + static EmployeeDatabaseSetupExtension FIRST_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbOne;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @RegisterExtension + static EmployeeDatabaseSetupExtension LAST_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbLast;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @Test + public void justDemonstratingTheIdea() { + // empty test + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java new file mode 100644 index 0000000000..a29fafd193 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung; + +import java.sql.SQLException; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; + +import com.baeldung.helpers.Employee; +import com.baeldung.extensions.EmployeeDaoParameterResolver; +import com.baeldung.extensions.EmployeeDatabaseSetupExtension; +import com.baeldung.extensions.EnvironmentExtension; +import com.baeldung.helpers.EmployeeJdbcDao; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith({ EnvironmentExtension.class, EmployeeDaoParameterResolver.class }) +public class ProgrammaticEmployeesUnitTest { + + private EmployeeJdbcDao employeeDao; + + @RegisterExtension static EmployeeDatabaseSetupExtension DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:AnotherDb;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + public ProgrammaticEmployeesUnitTest(EmployeeJdbcDao employeeDao) { + this.employeeDao = employeeDao; + } + + @Test + public void whenAddEmployee_thenGetEmployee() throws SQLException { + Employee emp = new Employee(1, "john"); + employeeDao.add(emp); + assertEquals(1, employeeDao.findAll().size()); + } + + @Test + public void whenGetEmployees_thenEmptyList() throws SQLException { + assertEquals(0, employeeDao.findAll().size()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java b/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java index 69e420b28a..f124703690 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java @@ -15,10 +15,20 @@ import com.baeldung.helpers.JdbcConnectionUtil; public class EmployeeDatabaseSetupExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { - private Connection con = JdbcConnectionUtil.getConnection(); - private EmployeeJdbcDao employeeDao = new EmployeeJdbcDao(con); + private Connection con; + private EmployeeJdbcDao employeeDao; private Savepoint savepoint; + public EmployeeDatabaseSetupExtension() { + con = JdbcConnectionUtil.getConnection(); + employeeDao = new EmployeeJdbcDao(con); + } + + public EmployeeDatabaseSetupExtension(String jdbcUrl, String driver, String username, String password) { + con = JdbcConnectionUtil.getConnection(jdbcUrl, driver, username, password); + employeeDao = new EmployeeJdbcDao(con); + } + @Override public void afterAll(ExtensionContext context) throws SQLException { if (con != null) { diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java index 7600f763cd..4b274cff39 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java @@ -19,7 +19,7 @@ public class EmployeeJdbcDao { } public void createTable() throws SQLException { - String createQuery = "CREATE TABLE employees(id long primary key, firstName varchar(50))"; + String createQuery = "CREATE TABLE IF NOT EXISTS employees(id long primary key, firstName varchar(50))"; PreparedStatement pstmt = con.prepareStatement(createQuery); pstmt.execute(); diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java index f380f9674c..ccba627234 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java @@ -11,22 +11,49 @@ public class JdbcConnectionUtil { private static Connection con; public static Connection getConnection() { - if (con == null) { + if (con == null || isClosed(con)) { try { Properties props = new Properties(); props.load(JdbcConnectionUtil.class.getResourceAsStream("jdbc.properties")); - Class.forName(props.getProperty("jdbc.driver")); - con = DriverManager.getConnection(props.getProperty("jdbc.url"), props.getProperty("jdbc.user"), props.getProperty("jdbc.password")); + + String jdbcUrl = props.getProperty("jdbc.url"); + String driver = props.getProperty("jdbc.driver"); + String username = props.getProperty("jdbc.user"); + String password = props.getProperty("jdbc.password"); + con = getConnection(jdbcUrl, driver, username, password); return con; } catch (IOException exc) { exc.printStackTrace(); + } + + return null; + } + return con; + } + + public static Connection getConnection(String jdbcUrl, String driver, String username, String password) { + if (con == null || isClosed(con)) { + try { + Class.forName(driver); + con = DriverManager.getConnection(jdbcUrl, username, password); + return con; } catch (ClassNotFoundException exc) { exc.printStackTrace(); } catch (SQLException exc) { exc.printStackTrace(); } + return null; } + return con; } + + private static boolean isClosed(Connection con) { + try { + return con.isClosed(); + } catch (SQLException e) { + return true; + } + } } diff --git a/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java b/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java index d1d08c6e62..d225e4547e 100644 --- a/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java +++ b/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java @@ -34,7 +34,7 @@ public class AssertionUnitTest { "heading", () -> assertEquals(4, 2 * 2, "4 is 2 times 2"), () -> assertEquals("java", "JAVA".toLowerCase()), - () -> assertEquals(null, null, "null is equal to null") + () -> assertEquals((String) null, (String) null, "null is equal to null") ); } }