diff --git a/.local-db/todos.mv.db b/.local-db/todos.mv.db new file mode 100644 index 0000000000..c081aa5aad Binary files /dev/null and b/.local-db/todos.mv.db differ diff --git a/.local-db/topics.mv.db b/.local-db/topics.mv.db new file mode 100644 index 0000000000..204bc60d70 Binary files /dev/null and b/.local-db/topics.mv.db differ diff --git a/README.md b/README.md index 88750cf654..1ae225b1f3 100644 --- a/README.md +++ b/README.md @@ -18,27 +18,33 @@ Java and Spring Tutorials This project is **a collection of small and focused tutorials** - each covering a single and well defined area of development in the Java ecosystem. A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Security. -In additional to Spring, the modules here are covering a number of aspects in Java. +In addition to Spring, the modules here cover a number of aspects of Java. Profile based segregation ==================== We are using maven build profiles to segregate the huge list of individual projects we have in our repository. -The projects are broadly divided into 3 list: first, second and heavy. +As for now, vast majority of the modules require JDK8 to build and run correctly. -Next, they are segregated further on the basis of tests that we want to execute. +The projects are broadly divided into 3 lists: first, second and heavy. -Therefore, we have a total of 6 profiles: +Next, they are segregated further on the basis of the tests that we want to execute. -| Profile | Includes | Type of test enabled | -| ----------------------- | --------------------------- | -------------------- | -| default-first | First set of projects | *UnitTest | -| integration-lite-first | First set of projects | *IntegrationTest | -| default-second | Second set of projects | *UnitTest | -| integration-lite-second | Second set of projects | *IntegrationTest | -| default-heavy | Heavy/long running projects | *UnitTest | -| integration-heavy | Heavy/long running projects | *IntegrationTest | +Additionally, there are 2 profiles dedicated for JDK9 and above builds. + +Therefore, we have a total of 8 profiles: + +| Profile | Includes | Type of test enabled | +| -------------------------- | --------------------------- | -------------------- | +| default-first | First set of projects | *UnitTest | +| integration-lite-first | First set of projects | *IntegrationTest | +| default-second | Second set of projects | *UnitTest | +| integration-lite-second | Second set of projects | *IntegrationTest | +| default-heavy | Heavy/long running projects | *UnitTest | +| integration-heavy | Heavy/long running projects | *IntegrationTest | +| default-jdk9-and-above | JDK9 and above projects | *UnitTest | +| integration-jdk9-and-above | JDK9 and above projects | *IntegrationTest | Building the project ==================== @@ -53,15 +59,22 @@ or if we want to build the entire repository with Integration Tests enabled, we `mvn clean install -Pintegration-lite-first,integration-lite-second,integration-heavy` +Analogously, for the JDK9 and above projects the commands are: + +`mvn clean install -Pdefault-jdk9-and-above` + +and + +`mvn clean install -Pintegration-jdk9-and-above` Building a single module ==================== -To build a specific module run the command: `mvn clean install` in the module directory +To build a specific module, run the command: `mvn clean install` in the module directory. Running a Spring Boot module ==================== -To run a Spring Boot module run the command: `mvn spring-boot:run` in the module directory +To run a Spring Boot module, run the command: `mvn spring-boot:run` in the module directory. Working with the IDE @@ -81,11 +94,8 @@ To run the integration tests, use the command: `mvn clean install -Pintegration-lite-second` or -`mvn clean install -Pintegration-heavy` +`mvn clean install -Pintegration-heavy` or + +`mvn clean install -Pintegration-jdk9-and-above` depending on the list where our module exists - - - - - diff --git a/akka-http/pom.xml b/akka-http/pom.xml index 4b73fbc960..a64d7a80f6 100644 --- a/akka-http/pom.xml +++ b/akka-http/pom.xml @@ -41,4 +41,4 @@ 2.5.11 - + \ No newline at end of file diff --git a/algorithms-genetic/pom.xml b/algorithms-genetic/pom.xml index 00c9b88dfe..c53ae0f776 100644 --- a/algorithms-genetic/pom.xml +++ b/algorithms-genetic/pom.xml @@ -35,18 +35,11 @@ jenetics ${io.jenetics.version} - - org.assertj - assertj-core - ${org.assertj.core.version} - test - 3.6.1 3.7.0 - 3.9.0 1.11 diff --git a/algorithms-genetic/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java b/algorithms-genetic/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java index 3139b49586..7ea556b7fe 100644 --- a/algorithms-genetic/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java +++ b/algorithms-genetic/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java @@ -18,15 +18,16 @@ public class Travel { } public void generateInitialTravel() { - if (travel.isEmpty()) + if (travel.isEmpty()) { new Travel(10); + } Collections.shuffle(travel); } public void swapCities() { int a = generateRandomIndex(); int b = generateRandomIndex(); - previousTravel = travel; + previousTravel = new ArrayList<>(travel); City x = travel.get(a); City y = travel.get(b); travel.set(a, y); diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index dd3742d4b0..c6f247f4e3 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -35,12 +35,6 @@ ${lombok.version} provided - - org.assertj - assertj-core - ${org.assertj.core.version} - test - com.github.dpaukov combinatoricslib3 @@ -70,9 +64,7 @@ 3.6.1 - 3.9.0 1.11 - 27.0.1-jre 3.3.0 2.7 diff --git a/algorithms-miscellaneous-2/pom.xml b/algorithms-miscellaneous-2/pom.xml index fcefc3ccba..a411cfdb71 100644 --- a/algorithms-miscellaneous-2/pom.xml +++ b/algorithms-miscellaneous-2/pom.xml @@ -45,12 +45,6 @@ tradukisto ${tradukisto.version} - - org.assertj - assertj-core - ${org.assertj.core.version} - test - @@ -78,7 +72,6 @@ 1.0.1 1.0.1 1.0.1 - 3.9.0 1.11 2.7 diff --git a/algorithms-miscellaneous-3/pom.xml b/algorithms-miscellaneous-3/pom.xml index 19eca8eca7..2f180da5e1 100644 --- a/algorithms-miscellaneous-3/pom.xml +++ b/algorithms-miscellaneous-3/pom.xml @@ -14,12 +14,6 @@ - - org.assertj - assertj-core - ${org.assertj.core.version} - test - org.apache.commons commons-collections4 @@ -43,7 +37,7 @@ org.apache.commons commons-lang3 - ${commons.lang3.version} + ${commons-lang3.version} pl.pragmatists @@ -69,11 +63,7 @@ - 3.9.0 - 4.3 - 28.0-jre 2.6.0 - 3.8.1 1.1.0 diff --git a/algorithms-miscellaneous-4/pom.xml b/algorithms-miscellaneous-4/pom.xml index 1eae038bc0..1dc9a62f64 100644 --- a/algorithms-miscellaneous-4/pom.xml +++ b/algorithms-miscellaneous-4/pom.xml @@ -25,17 +25,6 @@ ${lombok.version} provided - - org.assertj - assertj-core - ${org.assertj.core.version} - test - - - 3.9.0 - 27.0.1-jre - - \ No newline at end of file diff --git a/algorithms-miscellaneous-5/pom.xml b/algorithms-miscellaneous-5/pom.xml index 32ecce58a6..7ceede9cb9 100644 --- a/algorithms-miscellaneous-5/pom.xml +++ b/algorithms-miscellaneous-5/pom.xml @@ -34,25 +34,12 @@ guava ${guava.version} - - org.junit.platform - junit-platform-commons - ${junit-platform.version} - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - 1.0.1 - 3.9.0 1.11 3.6.1 - 28.1-jre \ No newline at end of file diff --git a/algorithms-miscellaneous-6/pom.xml b/algorithms-miscellaneous-6/pom.xml index 6d5f211c8a..584ec8a8dd 100644 --- a/algorithms-miscellaneous-6/pom.xml +++ b/algorithms-miscellaneous-6/pom.xml @@ -19,17 +19,6 @@ guava ${guava.version} - - org.junit.platform - junit-platform-commons - ${junit-platform.version} - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - org.projectlombok lombok @@ -44,8 +33,6 @@ - 28.1-jre - 3.9.0 3.6.1 diff --git a/algorithms-miscellaneous-6/src/main/java/com/baeldung/algorithms/caesarcipher/CaesarCipher.java b/algorithms-miscellaneous-6/src/main/java/com/baeldung/algorithms/caesarcipher/CaesarCipher.java index 5ee913d251..f14aa2b0d2 100644 --- a/algorithms-miscellaneous-6/src/main/java/com/baeldung/algorithms/caesarcipher/CaesarCipher.java +++ b/algorithms-miscellaneous-6/src/main/java/com/baeldung/algorithms/caesarcipher/CaesarCipher.java @@ -1,11 +1,16 @@ package com.baeldung.algorithms.caesarcipher; import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.stream.IntStream; public class CaesarCipher { + + private final Logger log = LoggerFactory.getLogger(CaesarCipher.class); + private static final char LETTER_A = 'a'; private static final char LETTER_Z = 'z'; private static final int ALPHABET_SIZE = LETTER_Z - LETTER_A + 1; @@ -72,7 +77,7 @@ public class CaesarCipher { private int probableOffset(double[] chiSquares) { int probableOffset = 0; for (int offset = 0; offset < chiSquares.length; offset++) { - System.out.println(String.format("Chi-Square for offset %d: %.2f", offset, chiSquares[offset])); + log.debug(String.format("Chi-Square for offset %d: %.2f", offset, chiSquares[offset])); if (chiSquares[offset] < chiSquares[probableOffset]) { probableOffset = offset; } diff --git a/guest/core-java-9/src/main/resources/logback.xml b/algorithms-miscellaneous-6/src/main/resources/logback.xml similarity index 100% rename from guest/core-java-9/src/main/resources/logback.xml rename to algorithms-miscellaneous-6/src/main/resources/logback.xml diff --git a/algorithms-searching/pom.xml b/algorithms-searching/pom.xml index a67c062403..edb8a0c423 100644 --- a/algorithms-searching/pom.xml +++ b/algorithms-searching/pom.xml @@ -13,15 +13,6 @@ 1.0.0-SNAPSHOT - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - - - algorithms-searching @@ -32,8 +23,4 @@ - - 3.9.0 - - \ No newline at end of file diff --git a/algorithms-searching/src/main/java/com/baeldung/algorithms/breadthfirstsearch/BreadthFirstSearchAlgorithm.java b/algorithms-searching/src/main/java/com/baeldung/algorithms/breadthfirstsearch/BreadthFirstSearchAlgorithm.java index 9d301f9578..ef1c7393c8 100644 --- a/algorithms-searching/src/main/java/com/baeldung/algorithms/breadthfirstsearch/BreadthFirstSearchAlgorithm.java +++ b/algorithms-searching/src/main/java/com/baeldung/algorithms/breadthfirstsearch/BreadthFirstSearchAlgorithm.java @@ -16,7 +16,7 @@ public class BreadthFirstSearchAlgorithm { Tree currentNode; while (!queue.isEmpty()) { currentNode = queue.remove(); - LOGGER.info("Visited node with value: {}", currentNode.getValue()); + LOGGER.debug("Visited node with value: {}", currentNode.getValue()); if (currentNode.getValue().equals(value)) { return Optional.of(currentNode); @@ -37,7 +37,7 @@ public class BreadthFirstSearchAlgorithm { while (!queue.isEmpty()) { currentNode = queue.remove(); - LOGGER.info("Visited node with value: {}", currentNode.getValue()); + LOGGER.debug("Visited node with value: {}", currentNode.getValue()); if (currentNode.getValue().equals(value)) { return Optional.of(currentNode); diff --git a/algorithms-searching/src/test/java/com/baeldung/algorithms/quadtree/QuadTreeSearchUnitTest.java b/algorithms-searching/src/test/java/com/baeldung/algorithms/quadtree/QuadTreeSearchUnitTest.java index faf06ced31..4389795ffb 100644 --- a/algorithms-searching/src/test/java/com/baeldung/algorithms/quadtree/QuadTreeSearchUnitTest.java +++ b/algorithms-searching/src/test/java/com/baeldung/algorithms/quadtree/QuadTreeSearchUnitTest.java @@ -35,6 +35,7 @@ public class QuadTreeSearchUnitTest { public void givenQuadTree_whenSearchingForRange_thenReturn1MatchingItem() { Region searchArea = new Region(200, 200, 250, 250); List result = quadTree.search(searchArea, null, ""); + LOGGER.debug(result.toString()); LOGGER.debug(quadTree.printSearchTraversePath()); @@ -47,6 +48,7 @@ public class QuadTreeSearchUnitTest { public void givenQuadTree_whenSearchingForRange_thenReturn2MatchingItems() { Region searchArea = new Region(0, 0, 100, 100); List result = quadTree.search(searchArea, null, ""); + LOGGER.debug(result.toString()); LOGGER.debug(quadTree.printSearchTraversePath()); diff --git a/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java b/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java index ef4a05a9a1..d9a4f2962c 100644 --- a/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java +++ b/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java @@ -24,7 +24,7 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForA_thenReturn6Matches() { List matches = suffixTree.searchText("a"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] { "h[a]vanabanana", "hav[a]nabanana", "havan[a]banana", "havanab[a]nana", "havanaban[a]na", "havanabanan[a]" }, matches.toArray()); } @@ -32,7 +32,7 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForNab_thenReturn1Match() { List matches = suffixTree.searchText("nab"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] { "hava[nab]anana" }, matches.toArray()); } @@ -40,7 +40,7 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForNag_thenReturnNoMatches() { List matches = suffixTree.searchText("nag"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] {}, matches.toArray()); } @@ -48,7 +48,7 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForBanana_thenReturn2Matches() { List matches = suffixTree.searchText("ana"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] { "hav[ana]banana", "havanab[ana]na", "havanaban[ana]" }, matches.toArray()); } @@ -56,7 +56,7 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForNa_thenReturn4Matches() { List matches = suffixTree.searchText("na"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] { "hava[na]banana", "havanaba[na]na", "havanabana[na]" }, matches.toArray()); } @@ -64,14 +64,14 @@ public class SuffixTreeUnitTest { public void givenSuffixTree_whenSearchingForX_thenReturnNoMatches() { List matches = suffixTree.searchText("x"); matches.stream() - .forEach(m -> LOGGER.info(m)); + .forEach(m -> LOGGER.debug(m)); Assert.assertArrayEquals(new String[] {}, matches.toArray()); } private static void printTree() { suffixTree.printTree(); - LOGGER.info("\n" + suffixTree.printTree()); - LOGGER.info("=============================================="); + LOGGER.debug("\n" + suffixTree.printTree()); + LOGGER.debug("=============================================="); } } diff --git a/algorithms-sorting-2/pom.xml b/algorithms-sorting-2/pom.xml index b673af9d70..a8477bf624 100644 --- a/algorithms-sorting-2/pom.xml +++ b/algorithms-sorting-2/pom.xml @@ -29,23 +29,10 @@ ${lombok.version} provided - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - 3.6.1 - 3.9.0 1.11 diff --git a/algorithms-sorting/pom.xml b/algorithms-sorting/pom.xml index b853fd80ee..383014d528 100644 --- a/algorithms-sorting/pom.xml +++ b/algorithms-sorting/pom.xml @@ -30,23 +30,10 @@ ${lombok.version} provided - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - 3.6.1 - 3.9.0 1.11 diff --git a/apache-kafka/pom.xml b/apache-kafka/pom.xml index 8003743f95..b373d78dd1 100644 --- a/apache-kafka/pom.xml +++ b/apache-kafka/pom.xml @@ -98,12 +98,6 @@ jackson-databind ${jackson.version} - - org.assertj - assertj-core - ${assertj.version} - test - org.testcontainers kafka @@ -170,13 +164,11 @@ - 3.6.2 2.8.0 1.15.3 1.15.3 1.5.0 3.0.0 - 29.0-jre 2.4.8 0.8.1-spark3.0-s_2.12 2.5.2 diff --git a/apache-libraries/pom.xml b/apache-libraries/pom.xml index b4cf11b07d..3d78869865 100644 --- a/apache-libraries/pom.xml +++ b/apache-libraries/pom.xml @@ -156,13 +156,6 @@ solr-solrj ${solr.solr-solrj.version} - - - org.assertj - assertj-core - ${assertj.version} - test - @@ -202,7 +195,6 @@ 1.8 1.8.2 2.19.0 - 3.9.0 1.1.2 1.1.0.Final 1.2.0 diff --git a/apache-olingo/olingo2/.gitignore b/apache-olingo/.gitignore similarity index 99% rename from apache-olingo/olingo2/.gitignore rename to apache-olingo/.gitignore index 153c9335eb..b85b366850 100644 --- a/apache-olingo/olingo2/.gitignore +++ b/apache-olingo/.gitignore @@ -27,3 +27,4 @@ HELP.md ### VS Code ### .vscode/ + diff --git a/apache-olingo/Samples.md b/apache-olingo/Samples.md index def8971d64..66f514b4d9 100644 --- a/apache-olingo/Samples.md +++ b/apache-olingo/Samples.md @@ -4,15 +4,15 @@ This following table contains test URLs that can be used with the Olingo V2 demo | URL | Description | |------------------------------------------|-------------------------------------------------| -| `http://localhost:8180/odata/$metadata` | fetch OData metadata document | -| `http://localhost:8180/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 | -| `http://localhost:8180/odata/CarMakers?$count` | Return total count of entities in this set | -| `http://localhost:8180/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' | -| `http://localhost:8180/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' | -| `http://localhost:8180/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker| -| `http://localhost:8180/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties | -| `http://localhost:8180/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties | -| `http://localhost:8180/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation| +| `http://localhost:8080/odata/$metadata` | fetch OData metadata document | +| `http://localhost:8080/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 | +| `http://localhost:8080/odata/CarMakers?$count` | Return total count of entities in this set | +| `http://localhost:8080/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' | +| `http://localhost:8080/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' | +| `http://localhost:8080/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker| +| `http://localhost:8080/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties | +| `http://localhost:8080/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties | +| `http://localhost:8080/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation| diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/pom.xml similarity index 85% rename from apache-olingo/olingo2/pom.xml rename to apache-olingo/pom.xml index c86428d054..5de0dfd511 100644 --- a/apache-olingo/olingo2/pom.xml +++ b/apache-olingo/pom.xml @@ -3,16 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung.examples.olingo2 - olingo2 - olingo2 - Sample Olingo 2 Project + com.baeldung.examples.olingo + apache-olingo + apache-olingo + Sample Apache Olingo Project com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../parent-boot-2 @@ -43,7 +43,7 @@ org.apache.olingo olingo-odata2-core - ${olingo2.version} + ${olingo.version} @@ -55,12 +55,12 @@ org.apache.olingo olingo-odata2-jpa-processor-core - ${olingo2.version} + ${olingo.version} org.apache.olingo olingo-odata2-jpa-processor-ref - ${olingo2.version} + ${olingo.version} org.eclipse.persistence @@ -80,7 +80,7 @@ - 2.0.11 + 2.0.11 - \ No newline at end of file + diff --git a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java similarity index 97% rename from apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java rename to apache-olingo/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java index 55155732c8..343af93de9 100644 --- a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java +++ b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java @@ -27,11 +27,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -/** - * ODataJPAServiceFactory implementation for our sample domain - * @author Philippe - * - */ @Component public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { @@ -44,7 +39,7 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { /** * This method will be called by Olingo on every request to - * initialize the ODataJPAContext that will be used. + * initialize the ODataJPAContext that will be used. */ @Override public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException { @@ -54,14 +49,14 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { ODataContext octx = ctx.getODataContext(); HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT); EntityManager em = (EntityManager)request.getAttribute(JerseyConfig.EntityManagerFilter.EM_REQUEST_ATTRIBUTE); - + // Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig) ctx.setEntityManager(new EntityManagerWrapper(em)); ctx.setPersistenceUnitName("default"); - + // We're managing the EM's lifecycle, so we must inform Olingo that it should not // try to manage transactions and/or persistence sessions - ctx.setContainerManaged(true); + ctx.setContainerManaged(true); return ctx; } diff --git a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java similarity index 89% rename from apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java rename to apache-olingo/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java index 02e5ce5adf..f300f552fe 100644 --- a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java +++ b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/JerseyConfig.java @@ -1,6 +1,12 @@ - package com.baeldung.examples.olingo2; +package com.baeldung.examples.olingo2; -import java.io.IOException; +import org.apache.olingo.odata2.api.ODataServiceFactory; +import org.apache.olingo.odata2.core.rest.ODataRootLocator; +import org.apache.olingo.odata2.core.rest.app.ODataApplication; +import org.glassfish.jersey.server.ResourceConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @@ -15,28 +21,15 @@ import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.Context; import javax.ws.rs.ext.Provider; -import org.apache.olingo.odata2.api.ODataServiceFactory; -import org.apache.olingo.odata2.core.rest.ODataRootLocator; -import org.apache.olingo.odata2.core.rest.app.ODataApplication; -import org.glassfish.jersey.server.ResourceConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -/** - * Jersey JAX-RS configuration - * @author Philippe - * - */ @Component @ApplicationPath("/odata") public class JerseyConfig extends ResourceConfig { - - - public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) { - + + + public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) { + ODataApplication app = new ODataApplication(); - + app .getClasses() .forEach( c -> { @@ -46,11 +39,11 @@ public class JerseyConfig extends ResourceConfig { register(c); } }); - - register(new CarsRootLocator(serviceFactory)); + + register(new CarsRootLocator(serviceFactory)); register( new EntityManagerFilter(emf)); } - + /** * This filter handles the EntityManager transaction lifecycle. * @author Philippe @@ -72,7 +65,7 @@ public class JerseyConfig extends ResourceConfig { } @Override - public void filter(ContainerRequestContext ctx) throws IOException { + public void filter(ContainerRequestContext ctx) { log.info("[I60] >>> filter"); EntityManager em = this.emf.createEntityManager(); httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em); @@ -85,7 +78,7 @@ public class JerseyConfig extends ResourceConfig { } @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) { log.info("[I68] <<< filter"); EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE); diff --git a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java similarity index 88% rename from apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java rename to apache-olingo/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java index f76e0e00e3..7210f4c812 100644 --- a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java +++ b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/Olingo2SampleApplication.java @@ -7,7 +7,7 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer @SpringBootApplication public class Olingo2SampleApplication extends SpringBootServletInitializer { - public static void main(String[] args) { + public static void main(String[] args) { SpringApplication.run(Olingo2SampleApplication.class); } } diff --git a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/domain/CarMaker.java b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/domain/CarMaker.java similarity index 100% rename from apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/domain/CarMaker.java rename to apache-olingo/src/main/java/com/baeldung/examples/olingo2/domain/CarMaker.java diff --git a/apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/domain/CarModel.java b/apache-olingo/src/main/java/com/baeldung/examples/olingo2/domain/CarModel.java similarity index 100% rename from apache-olingo/olingo2/src/main/java/com/baeldung/examples/olingo2/domain/CarModel.java rename to apache-olingo/src/main/java/com/baeldung/examples/olingo2/domain/CarModel.java diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/src/main/resources/application.yml similarity index 100% rename from apache-olingo/olingo2/src/main/resources/application.yml rename to apache-olingo/src/main/resources/application.yml diff --git a/apache-olingo/olingo2/src/main/resources/data.sql b/apache-olingo/src/main/resources/data.sql similarity index 100% rename from apache-olingo/olingo2/src/main/resources/data.sql rename to apache-olingo/src/main/resources/data.sql diff --git a/guest/deep-jsf/src/main/resources/logback.xml b/apache-olingo/src/main/resources/logback.xml similarity index 100% rename from guest/deep-jsf/src/main/resources/logback.xml rename to apache-olingo/src/main/resources/logback.xml diff --git a/apache-olingo/olingo2/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationUnitTest.java b/apache-olingo/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationIntegrationTest.java similarity index 84% rename from apache-olingo/olingo2/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationUnitTest.java rename to apache-olingo/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationIntegrationTest.java index 74033a49cd..402c288673 100644 --- a/apache-olingo/olingo2/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationUnitTest.java +++ b/apache-olingo/src/test/java/com/baeldung/examples/olingo2/Olingo2SampleApplicationIntegrationTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -public class Olingo2SampleApplicationUnitTest { +public class Olingo2SampleApplicationIntegrationTest { @Test public void contextLoads() { diff --git a/apache-olingo/src/test/resources/logback-test.xml b/apache-olingo/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/apache-olingo/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/apache-olingo/olingo2/src/test/resources/olingo2-queries.json b/apache-olingo/src/test/resources/olingo2-queries.json similarity index 100% rename from apache-olingo/olingo2/src/test/resources/olingo2-queries.json rename to apache-olingo/src/test/resources/olingo2-queries.json diff --git a/apache-poi-2/.gitignore b/apache-poi-2/.gitignore new file mode 100644 index 0000000000..d5c7c78cb1 --- /dev/null +++ b/apache-poi-2/.gitignore @@ -0,0 +1,4 @@ +*.docx +temp.xls +temp.xlsx +number_test.xlsx diff --git a/apache-poi-2/README.md b/apache-poi-2/README.md new file mode 100644 index 0000000000..2fd0135b11 --- /dev/null +++ b/apache-poi-2/README.md @@ -0,0 +1,12 @@ +## Apache POI + +This module contains articles about Apache POI. + +### Relevant Articles: + +- [Adding a Column to an Excel Sheet Using Apache POI](https://www.baeldung.com/java-excel-add-column) +- [Add an Image to a Cell in an Excel File With Java](https://www.baeldung.com/java-add-image-excel) +- [Numeric Format Using POI](https://www.baeldung.com/apache-poi-numeric-format) +- [Microsoft Word Processing in Java with Apache POI](https://www.baeldung.com/java-microsoft-word-with-apache-poi) +- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow) +- More articles: [[<-- prev]](../apache-poi) diff --git a/guest/logback-example/pom.xml b/apache-poi-2/pom.xml similarity index 51% rename from guest/logback-example/pom.xml rename to apache-poi-2/pom.xml index e7e83c743f..a46365c63c 100644 --- a/guest/logback-example/pom.xml +++ b/apache-poi-2/pom.xml @@ -1,28 +1,29 @@ - 4.0.0 - com.stackify - logback-example + apache-poi-2 0.0.1-SNAPSHOT - logback-example + apache-poi-2 com.baeldung parent-modules 1.0.0-SNAPSHOT - ../../ - org.codehaus.janino - janino - ${janino.version} + org.apache.poi + poi-ooxml + ${poi.version} - 3.0.7 + 5.0.0 - \ No newline at end of file + + + diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/ExcelColumn.java b/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/ExcelColumn.java new file mode 100644 index 0000000000..00ca24f6e8 --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/ExcelColumn.java @@ -0,0 +1,16 @@ +package com.baeldung.poi.excel.newcolumn; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + + +public class ExcelColumn { + + public void addColumn(Sheet sheet, CellType cellType) { + for (Row currentRow : sheet) { + currentRow.createCell(currentRow.getLastCellNum(), cellType); + } + } +} diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/numeric/ExcelNumericFormat.java b/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/numeric/ExcelNumericFormat.java new file mode 100644 index 0000000000..02148c783b --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/excel/newcolumn/numeric/ExcelNumericFormat.java @@ -0,0 +1,19 @@ +package com.baeldung.poi.excel.newcolumn.numeric; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Workbook; + +public class ExcelNumericFormat { + + public static void applyNumericFormat(Workbook outWorkbook, Row row, Cell cell, Double value, String styleFormat) { + CellStyle style = outWorkbook.createCellStyle(); + DataFormat format = outWorkbook.createDataFormat(); + style.setDataFormat(format.getFormat(styleFormat)); + cell.setCellValue(value); + cell.setCellStyle(style); + } + +} diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/excel/write/addimageincell/ExcelCellImageHelper.java b/apache-poi-2/src/main/java/com/baeldung/poi/excel/write/addimageincell/ExcelCellImageHelper.java new file mode 100644 index 0000000000..6bd4f9d66b --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/excel/write/addimageincell/ExcelCellImageHelper.java @@ -0,0 +1,76 @@ +package com.baeldung.poi.excel.write.addimageincell; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDrawing; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * This Helper class Add an Image to a Cell of an Excel File With apache-poi api. + * + */ +public class ExcelCellImageHelper { + + public static void main(String[] args) throws IOException, InvalidFormatException { + try (final Workbook workbook = new XSSFWorkbook(); + FileOutputStream saveExcel = new FileOutputStream("target/baeldung-apachepoi.xlsx");) { + + Sheet sheet = workbook.createSheet("Avengers"); + + XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch(); + XSSFClientAnchor ironManAnchor = new XSSFClientAnchor(); + XSSFClientAnchor spiderManAnchor = new XSSFClientAnchor(); + + // Fill row1 data + Row row1 = sheet.createRow(0); + row1.setHeight((short) 1000); + row1.createCell(0) + .setCellValue("IRON-MAN"); + updateCellWithImage(workbook, 1, drawing, ironManAnchor, "ironman.png"); + + // Fill row2 data + Row row2 = sheet.createRow(1); + row2.setHeight((short) 1000); + row2.createCell(0) + .setCellValue("SPIDER-MAN"); + updateCellWithImage(workbook, 2, drawing, spiderManAnchor, "spiderman.png"); + + // Resize all columns to fit the content size + for (int i = 0; i < 2; i++) { + sheet.autoSizeColumn(i); + } + workbook.write(saveExcel); + } + + } + + /** + * This method position the anchor for a given rowNum and add the image correctly. + * @param workbook + * @param rowNum + * @param drawing + * @param inputImageAnchor + * @throws IOException + */ + private static void updateCellWithImage(Workbook workbook, int rowNum, XSSFDrawing drawing, XSSFClientAnchor inputImageAnchor, String inputImageName) throws IOException { + InputStream inputImageStream = ExcelCellImageHelper.class.getClassLoader() + .getResourceAsStream(inputImageName); + byte[] inputImageBytes = IOUtils.toByteArray(inputImageStream); + int inputImagePictureID = workbook.addPicture(inputImageBytes, Workbook.PICTURE_TYPE_PNG); + inputImageStream.close(); + inputImageAnchor.setCol1(1); + inputImageAnchor.setRow1(rowNum - 1); + inputImageAnchor.setCol2(2); + inputImageAnchor.setRow2(rowNum); + drawing.createPicture(inputImageAnchor, inputImagePictureID); + } + +} diff --git a/apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java b/apache-poi-2/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java similarity index 89% rename from apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java rename to apache-poi-2/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java index e2af4f8808..5b40301de5 100644 --- a/apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java +++ b/apache-poi-2/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java @@ -5,7 +5,22 @@ import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.TableCell; import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.util.IOUtils; -import org.apache.poi.xslf.usermodel.*; +import org.apache.poi.xslf.usermodel.SlideLayout; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xslf.usermodel.XSLFAutoShape; +import org.apache.poi.xslf.usermodel.XSLFHyperlink; +import org.apache.poi.xslf.usermodel.XSLFPictureData; +import org.apache.poi.xslf.usermodel.XSLFPictureShape; +import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.poi.xslf.usermodel.XSLFSlide; +import org.apache.poi.xslf.usermodel.XSLFSlideLayout; +import org.apache.poi.xslf.usermodel.XSLFSlideMaster; +import org.apache.poi.xslf.usermodel.XSLFTable; +import org.apache.poi.xslf.usermodel.XSLFTableCell; +import org.apache.poi.xslf.usermodel.XSLFTableRow; +import org.apache.poi.xslf.usermodel.XSLFTextParagraph; +import org.apache.poi.xslf.usermodel.XSLFTextRun; +import org.apache.poi.xslf.usermodel.XSLFTextShape; import java.awt.*; import java.io.FileInputStream; @@ -155,8 +170,8 @@ public class PowerPointHelper { /** * Retrieve the placeholder inside a slide - * - * @param slide + * + * @param slide * The slide * @return List of placeholder inside a slide */ diff --git a/apache-poi/src/main/java/com/baeldung/poi/word/WordDocument.java b/apache-poi-2/src/main/java/com/baeldung/poi/word/WordDocument.java similarity index 93% rename from apache-poi/src/main/java/com/baeldung/poi/word/WordDocument.java rename to apache-poi-2/src/main/java/com/baeldung/poi/word/WordDocument.java index 599da86eaa..ee754beeb9 100644 --- a/apache-poi/src/main/java/com/baeldung/poi/word/WordDocument.java +++ b/apache-poi-2/src/main/java/com/baeldung/poi/word/WordDocument.java @@ -1,7 +1,11 @@ package com.baeldung.poi.word; import org.apache.poi.util.Units; -import org.apache.poi.xwpf.usermodel.*; +import org.apache.poi.xwpf.usermodel.ParagraphAlignment; +import org.apache.poi.xwpf.usermodel.UnderlinePatterns; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; import java.io.FileOutputStream; import java.io.IOException; diff --git a/apache-poi-2/src/main/resources/ironman.png b/apache-poi-2/src/main/resources/ironman.png new file mode 100644 index 0000000000..30096294c9 Binary files /dev/null and b/apache-poi-2/src/main/resources/ironman.png differ diff --git a/apache-poi/src/main/resources/logo-leaf.png b/apache-poi-2/src/main/resources/logo-leaf.png similarity index 100% rename from apache-poi/src/main/resources/logo-leaf.png rename to apache-poi-2/src/main/resources/logo-leaf.png diff --git a/apache-poi/src/main/resources/poi-word-para1.txt b/apache-poi-2/src/main/resources/poi-word-para1.txt similarity index 100% rename from apache-poi/src/main/resources/poi-word-para1.txt rename to apache-poi-2/src/main/resources/poi-word-para1.txt diff --git a/apache-poi/src/main/resources/poi-word-para2.txt b/apache-poi-2/src/main/resources/poi-word-para2.txt similarity index 100% rename from apache-poi/src/main/resources/poi-word-para2.txt rename to apache-poi-2/src/main/resources/poi-word-para2.txt diff --git a/apache-poi/src/main/resources/poi-word-para3.txt b/apache-poi-2/src/main/resources/poi-word-para3.txt similarity index 100% rename from apache-poi/src/main/resources/poi-word-para3.txt rename to apache-poi-2/src/main/resources/poi-word-para3.txt diff --git a/apache-poi-2/src/main/resources/spiderman.png b/apache-poi-2/src/main/resources/spiderman.png new file mode 100644 index 0000000000..32982bbe65 Binary files /dev/null and b/apache-poi-2/src/main/resources/spiderman.png differ diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/ExcelColumnUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/ExcelColumnUnitTest.java new file mode 100644 index 0000000000..9b991719b1 --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/ExcelColumnUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.poi.excel.newcolumn; + +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + +public class ExcelColumnUnitTest { + private static final String FILE_NAME = "newColumnTest.xlsx"; + private String fileLocation; + + @Before + public void setup() throws URISyntaxException { + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString(); + } + + @Test + public void givenExistingRows_whenAddNewColumn_thenRowColumnNumberIncreased() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(0); + Row row = sheet.getRow(0); + assertEquals(5, row.getLastCellNum()); + + ExcelColumn excelColumn = new ExcelColumn(); + excelColumn.addColumn(sheet, CellType.STRING); + assertEquals(6, row.getLastCellNum()); + + workbook.close(); + } + +} \ No newline at end of file diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/numeric/NumberCellValueUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/numeric/NumberCellValueUnitTest.java new file mode 100644 index 0000000000..ae1090fd69 --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/excel/newcolumn/numeric/NumberCellValueUnitTest.java @@ -0,0 +1,105 @@ +package com.baeldung.poi.excel.newcolumn.numeric; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.DecimalFormat; + +public class NumberCellValueUnitTest { + + @Test + public void decimalDisplay_whenAddedDouble_thenNumericCellCreated() throws IOException { + File file = new File("number_test.xlsx"); + try (Workbook outWorkbook = new XSSFWorkbook()) { + Sheet sheet = outWorkbook.createSheet("Numeric Sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + ExcelNumericFormat.applyNumericFormat(outWorkbook, row, cell, 10.251, "0.00"); + FileOutputStream fileOut = new FileOutputStream(file); + outWorkbook.write(fileOut); + fileOut.close(); + } + try (Workbook inWorkbook = new XSSFWorkbook("number_test.xlsx")) { + Sheet sheet = inWorkbook.cloneSheet(0); + Row row = sheet.getRow(0); + Assertions.assertEquals(10.251, row.getCell(0) + .getNumericCellValue()); + file.delete(); + } + } + + @Test + public void decimalRoundedDisplay_whenAddedDouble_thenNumericCellCreated() throws IOException { + File file = new File("number_test.xlsx"); + try (Workbook outWorkbook = new XSSFWorkbook()) { + Sheet sheet = outWorkbook.createSheet("Numeric Sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + ExcelNumericFormat.applyNumericFormat(outWorkbook, row, cell, 10.251123, "#,##0.0000"); + FileOutputStream fileOut = new FileOutputStream(file); + outWorkbook.write(fileOut); + fileOut.close(); + } + try (Workbook inWorkbook = new XSSFWorkbook("number_test.xlsx")) { + Sheet sheet = inWorkbook.cloneSheet(0); + Row row = sheet.getRow(0); + Assertions.assertEquals(10.251123, row.getCell(0) + .getNumericCellValue()); + file.delete(); + } + } + + @Test + public void decimalDisplayInXLS_whenAddedDouble_thenNumericCellCreated() throws IOException { + File file = new File("number_test.xls"); + try (Workbook outWorkbook = new HSSFWorkbook()) { + Sheet sheet = outWorkbook.createSheet("Numeric Sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + ExcelNumericFormat.applyNumericFormat(outWorkbook, row, cell, 10.251, "0.00"); + FileOutputStream fileOut = new FileOutputStream(file); + outWorkbook.write(fileOut); + fileOut.close(); + } + try (Workbook inWorkbook = new HSSFWorkbook(new FileInputStream(file))) { + Sheet sheet = inWorkbook.cloneSheet(0); + Row row = sheet.getRow(0); + Assertions.assertEquals(10.251, row.getCell(0) + .getNumericCellValue()); + file.delete(); + } + } + + @Test + public void decimalValue_whenAddedDouble_thenNumericCellCreated() throws IOException { + File file = new File("number_test.xlsx"); + try (Workbook outWorkbook = new XSSFWorkbook()) { + Sheet sheet = outWorkbook.createSheet("Numeric Sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + DecimalFormat df = new DecimalFormat("#,###.##"); + ExcelNumericFormat.applyNumericFormat(outWorkbook, row, cell, Double.valueOf(df.format(10.251)), "#,###.##"); + + FileOutputStream fileOut = new FileOutputStream(file); + outWorkbook.write(fileOut); + fileOut.close(); + } + try (Workbook inWorkbook = new XSSFWorkbook("number_test.xlsx")) { + Sheet sheet = inWorkbook.cloneSheet(0); + Row row = sheet.getRow(0); + Assertions.assertEquals(10.25, row.getCell(0) + .getNumericCellValue()); + file.delete(); + } + } +} \ No newline at end of file diff --git a/apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java similarity index 99% rename from apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java rename to apache-poi-2/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java index 7253238e80..aff0ab3821 100644 --- a/apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java +++ b/apache-poi-2/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java @@ -1,8 +1,5 @@ package com.baeldung.poi.powerpoint; -import java.io.File; -import java.util.List; - import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFShape; import org.apache.poi.xslf.usermodel.XSLFSlide; @@ -13,12 +10,15 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import java.io.File; +import java.util.List; + public class PowerPointIntegrationTest { private PowerPointHelper pph; private String fileLocation; private static final String FILE_NAME = "presentation.pptx"; - + @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); diff --git a/apache-poi/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java similarity index 100% rename from apache-poi/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java rename to apache-poi-2/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java index 98b5c5b520..fe83aa4a4d 100644 --- a/apache-poi/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java +++ b/apache-poi-2/src/test/java/com/baeldung/poi/word/WordIntegrationTest.java @@ -1,19 +1,19 @@ package com.baeldung.poi.word; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; - import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.junit.BeforeClass; import org.junit.Test; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class WordIntegrationTest { static WordDocument wordDocument; diff --git a/apache-poi-2/src/test/resources/newColumnTest.xlsx b/apache-poi-2/src/test/resources/newColumnTest.xlsx new file mode 100644 index 0000000000..54e8734d58 Binary files /dev/null and b/apache-poi-2/src/test/resources/newColumnTest.xlsx differ diff --git a/apache-poi/.gitignore b/apache-poi/.gitignore index 9552c1e63d..ac62b36227 100644 --- a/apache-poi/.gitignore +++ b/apache-poi/.gitignore @@ -1,3 +1,5 @@ *.docx temp.xls temp.xlsx + +CellStyleTest_output.xlsx \ No newline at end of file diff --git a/apache-poi/README.md b/apache-poi/README.md index d500787536..ed30d9a4f3 100644 --- a/apache-poi/README.md +++ b/apache-poi/README.md @@ -1,14 +1,18 @@ ## Apache POI -This module contains articles about Apache POI +This module contains articles about Apache POI. ### Relevant Articles: -- [Microsoft Word Processing in Java with Apache POI](https://www.baeldung.com/java-microsoft-word-with-apache-poi) - [Working with Microsoft Excel in Java](https://www.baeldung.com/java-microsoft-excel) -- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow) - [Merge Cells in Excel Using Apache POI](https://www.baeldung.com/java-apache-poi-merge-cells) - [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value) - [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula) - [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas) - [Insert a Row in Excel Using Apache POI](https://www.baeldung.com/apache-poi-insert-excel-row) +- [Multiline Text in Excel Cell Using Apache POI](https://www.baeldung.com/apache-poi-write-multiline-text) +- [Set Background Color of a Cell with Apache POI](https://www.baeldung.com/apache-poi-background-color) +- [Add Borders to Excel Cells With Apache POI](https://www.baeldung.com/apache-poi-add-borders) +- [Reading Values From Excel in Java](https://www.baeldung.com/java-read-dates-excel) +- [Change Cell Font Style with Apache POI](https://www.baeldung.com/apache-poi-change-cell-font) +- More articles: [[next -->]](../apache-poi-2) diff --git a/apache-poi/pom.xml b/apache-poi/pom.xml index 5471c77961..546eedec5b 100644 --- a/apache-poi/pom.xml +++ b/apache-poi/pom.xml @@ -32,9 +32,27 @@ + + + + org.apache.maven.plugins + maven-resources-plugin + ${maven.resources.plugin.version} + + UTF-8 + + xlsx + xls + + + + + + - 4.1.1 + 5.2.0 1.0.6 + 3.2.0 \ No newline at end of file diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java index b6b0cbef20..6c2a8c68f7 100644 --- a/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java @@ -1,25 +1,24 @@ package com.baeldung.poi.excel; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFFont; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.FillPatternType; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.List; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelPOIHelper { @@ -33,7 +32,7 @@ public class ExcelPOIHelper { for (Row row : sheet) { data.put(i, new ArrayList()); for (Cell cell : row) { - switch (cell.getCellTypeEnum()) { + switch (cell.getCellType()) { case STRING: data.get(i) .add(cell.getRichStringCellValue() diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java new file mode 100644 index 0000000000..f22b0f094f --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java @@ -0,0 +1,76 @@ +package com.baeldung.poi.excel; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +public class ExcelUtility { + private static final String ENDLINE = System.getProperty("line.separator"); + + public static String readExcel(String filePath) throws IOException { + File file = new File(filePath); + FileInputStream inputStream = null; + StringBuilder toReturn = new StringBuilder(); + try { + inputStream = new FileInputStream(file); + Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream); + for (Sheet sheet : baeuldungWorkBook) { + toReturn.append("--------------------------------------------------------------------") + .append(ENDLINE); + toReturn.append("Worksheet :") + .append(sheet.getSheetName()) + .append(ENDLINE); + toReturn.append("--------------------------------------------------------------------") + .append(ENDLINE); + int firstRow = sheet.getFirstRowNum(); + int lastRow = sheet.getLastRowNum(); + for (int index = firstRow + 1; index <= lastRow; index++) { + Row row = sheet.getRow(index); + toReturn.append("|| "); + for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) { + Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + printCellValue(cell, toReturn); + } + toReturn.append(" ||") + .append(ENDLINE); + } + } + inputStream.close(); + baeuldungWorkBook.close(); + + } catch (IOException e) { + throw e; + } + return toReturn.toString(); + } + + public static void printCellValue(Cell cell, StringBuilder toReturn) { + CellType cellType = cell.getCellType() + .equals(CellType.FORMULA) ? cell.getCachedFormulaResultType() : cell.getCellType(); + if (cellType.equals(CellType.STRING)) { + toReturn.append(cell.getStringCellValue()) + .append(" | "); + } + if (cellType.equals(CellType.NUMERIC)) { + if (DateUtil.isCellDateFormatted(cell)) { + toReturn.append(cell.getDateCellValue()) + .append(" | "); + } else { + toReturn.append(cell.getNumericCellValue()) + .append(" | "); + } + } + if (cellType.equals(CellType.BOOLEAN)) { + toReturn.append(cell.getBooleanCellValue()) + .append(" | "); + } + } +} \ No newline at end of file diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java.orig b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java.orig new file mode 100644 index 0000000000..c058f3abcf --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelUtility.java.orig @@ -0,0 +1,128 @@ +package com.baeldung.poi.excel; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +public class ExcelUtility { +<<<<<<< HEAD + private static final String ENDLINE = System.getProperty("line.separator"); + + public static String readExcel(String filePath) throws IOException { + File file = new File(filePath); + FileInputStream inputStream = null; + StringBuilder toReturn = new StringBuilder(); + try { + inputStream = new FileInputStream(file); + Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream); + for (Sheet sheet : baeuldungWorkBook) { + toReturn.append("--------------------------------------------------------------------") + .append(ENDLINE); + toReturn.append("Worksheet :") + .append(sheet.getSheetName()) + .append(ENDLINE); + toReturn.append("--------------------------------------------------------------------") + .append(ENDLINE); + int firstRow = sheet.getFirstRowNum(); + int lastRow = sheet.getLastRowNum(); + for (int index = firstRow + 1; index <= lastRow; index++) { + Row row = sheet.getRow(index); + toReturn.append("|| "); + for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) { + Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + printCellValue(cell, toReturn); + } + toReturn.append(" ||") + .append(ENDLINE); + } + } + inputStream.close(); + + } catch (IOException e) { + throw e; + } + return toReturn.toString(); + } + + public static void printCellValue(Cell cell, StringBuilder toReturn) { + CellType cellType = cell.getCellType() + .equals(CellType.FORMULA) ? cell.getCachedFormulaResultType() : cell.getCellType(); + if (cellType.equals(CellType.STRING)) { + toReturn.append(cell.getStringCellValue()) + .append(" | "); + } + if (cellType.equals(CellType.NUMERIC)) { + if (DateUtil.isCellDateFormatted(cell)) { + toReturn.append(cell.getDateCellValue()) + .append(" | "); + } else { + toReturn.append(cell.getNumericCellValue()) + .append(" | "); + } + } + if (cellType.equals(CellType.BOOLEAN)) { + toReturn.append(cell.getBooleanCellValue()) + .append(" | "); + } + } +======= + private static final String ENDLINE = System.getProperty("line.separator"); + + public static String readExcel(String filePath) throws IOException { + File file = new File(filePath); + FileInputStream inputStream = null; + StringBuilder toReturn = new StringBuilder(); + try { + inputStream = new FileInputStream(file); + Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream); + for (Sheet sheet : baeuldungWorkBook) { + toReturn.append("--------------------------------------------------------------------").append(ENDLINE); + toReturn.append("Worksheet :").append(sheet.getSheetName()).append(ENDLINE); + toReturn.append("--------------------------------------------------------------------").append(ENDLINE); + int firstRow = sheet.getFirstRowNum(); + int lastRow = sheet.getLastRowNum(); + for (int index = firstRow + 1; index <= lastRow; index++) { + Row row = sheet.getRow(index); + toReturn.append("|| "); + for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) { + Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + printCellValue(cell, toReturn); + } + toReturn.append(" ||").append(ENDLINE); + } + } + inputStream.close(); + + } catch (IOException e) { + throw e; + } + return toReturn.toString(); + } + + public static void printCellValue(Cell cell, StringBuilder toReturn) { + CellType cellType = cell.getCellType().equals(CellType.FORMULA) ? cell.getCachedFormulaResultType() + : cell.getCellType(); + if (cellType.equals(CellType.STRING)) { + toReturn.append(cell.getStringCellValue()).append(" | "); + } + if (cellType.equals(CellType.NUMERIC)) { + if (DateUtil.isCellDateFormatted(cell)) { + toReturn.append(cell.getDateCellValue()).append(" | "); + } else { + toReturn.append(cell.getNumericCellValue()).append(" | "); + } + } + if (cellType.equals(CellType.BOOLEAN)) { + toReturn.append(cell.getBooleanCellValue()).append(" | "); + } + } +>>>>>>> master +} \ No newline at end of file diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellBordersHandler.java b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellBordersHandler.java new file mode 100644 index 0000000000..1c96db0b60 --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellBordersHandler.java @@ -0,0 +1,37 @@ +package com.baeldung.poi.excel.cellstyle; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.RegionUtil; + +public class CellBordersHandler { + + public void setRegionBorder(CellRangeAddress region, Sheet sheet, BorderStyle borderStyle) { + RegionUtil.setBorderTop(borderStyle, region, sheet); + RegionUtil.setBorderBottom(borderStyle, region, sheet); + RegionUtil.setBorderLeft(borderStyle, region, sheet); + RegionUtil.setBorderRight(borderStyle, region, sheet); + } + + public void setRegionBorderWithColor(CellRangeAddress region, Sheet sheet, BorderStyle borderStyle, short color) { + RegionUtil.setTopBorderColor(color, region, sheet); + RegionUtil.setBottomBorderColor(color, region, sheet); + RegionUtil.setLeftBorderColor(color, region, sheet); + RegionUtil.setRightBorderColor(color, region, sheet); + RegionUtil.setBorderTop(borderStyle, region, sheet); + RegionUtil.setBorderBottom(borderStyle, region, sheet); + RegionUtil.setBorderLeft(borderStyle, region, sheet); + RegionUtil.setBorderRight(borderStyle, region, sheet); + } + + public void setCrazyBorder(CellRangeAddress region, Sheet sheet) { + RegionUtil.setTopBorderColor(IndexedColors.RED.index, region, sheet); + RegionUtil.setBottomBorderColor(IndexedColors.GREEN.index, region, sheet); + RegionUtil.setLeftBorderColor(IndexedColors.BLUE.index, region, sheet); + RegionUtil.setRightBorderColor(IndexedColors.VIOLET.index, region, sheet); + RegionUtil.setBorderTop(BorderStyle.DASH_DOT, region, sheet); + RegionUtil.setBorderBottom(BorderStyle.DOUBLE, region, sheet); + RegionUtil.setBorderLeft(BorderStyle.DOTTED, region, sheet); + RegionUtil.setBorderRight(BorderStyle.SLANTED_DASH_DOT, region, sheet); + } +} diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyleHandler.java b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyleHandler.java new file mode 100644 index 0000000000..4d97fe50cb --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyleHandler.java @@ -0,0 +1,30 @@ +package com.baeldung.poi.excel.cellstyle; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.IndexedColors; + +public class CellStyleHandler { + + public void changeCellBackgroundColor(Cell cell) { + CellStyle cellStyle = cell.getCellStyle(); + if(cellStyle == null) { + cellStyle = cell.getSheet().getWorkbook().createCellStyle(); + } + cellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + cell.setCellStyle(cellStyle); + } + + public void changeCellBackgroundColorWithPattern(Cell cell) { + CellStyle cellStyle = cell.getCellStyle(); + if(cellStyle == null) { + cellStyle = cell.getSheet().getWorkbook().createCellStyle(); + } + cellStyle.setFillBackgroundColor(IndexedColors.BLACK.index); + cellStyle.setFillPattern(FillPatternType.BIG_SPOTS); + cellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); + cell.setCellStyle(cellStyle); + } +} diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyler.java b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyler.java new file mode 100644 index 0000000000..0f8f8b6cd9 --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/cellstyle/CellStyler.java @@ -0,0 +1,25 @@ +package com.baeldung.poi.excel.cellstyle; + +import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; + +public class CellStyler { + public CellStyle createWarningColor(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + + Font font = workbook.createFont(); + font.setFontName("Courier New"); + font.setBold(true); + font.setUnderline(Font.U_SINGLE); + font.setColor(HSSFColorPredefined.DARK_RED.getIndex()); + style.setFont(font); + + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + return style; + } +} diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/multilinetext/MultilineText.java b/apache-poi/src/main/java/com/baeldung/poi/excel/multilinetext/MultilineText.java index 2e0cc5770e..231d7b8968 100644 --- a/apache-poi/src/main/java/com/baeldung/poi/excel/multilinetext/MultilineText.java +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/multilinetext/MultilineText.java @@ -2,7 +2,6 @@ package com.baeldung.poi.excel.multilinetext; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.Row; public class MultilineText { public void formatMultilineText(Cell cell, int cellNumber) { diff --git a/apache-poi/src/main/resources/cellstyle/CellStyleBorderHandlerTest.xlsx b/apache-poi/src/main/resources/cellstyle/CellStyleBorderHandlerTest.xlsx new file mode 100644 index 0000000000..29f128211b Binary files /dev/null and b/apache-poi/src/main/resources/cellstyle/CellStyleBorderHandlerTest.xlsx differ diff --git a/apache-poi/src/main/resources/cellstyle/CellStyleHandlerTest.xlsx b/apache-poi/src/main/resources/cellstyle/CellStyleHandlerTest.xlsx new file mode 100644 index 0000000000..29f128211b Binary files /dev/null and b/apache-poi/src/main/resources/cellstyle/CellStyleHandlerTest.xlsx differ diff --git a/apache-poi/src/main/resources/com/baeldung/poi/excel/cellstyle/CellStyle.xlsx b/apache-poi/src/main/resources/com/baeldung/poi/excel/cellstyle/CellStyle.xlsx new file mode 100644 index 0000000000..ca9394246a Binary files /dev/null and b/apache-poi/src/main/resources/com/baeldung/poi/excel/cellstyle/CellStyle.xlsx differ diff --git a/apache-poi/src/test/java/com/baeldung/jexcel/JExcelIntegrationTest.java b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelIntegrationTest.java index 41efd9d9ba..abf3d3d50c 100644 --- a/apache-poi/src/test/java/com/baeldung/jexcel/JExcelIntegrationTest.java +++ b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelIntegrationTest.java @@ -1,25 +1,18 @@ package com.baeldung.jexcel; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import jxl.read.biff.BiffException; -import java.util.Map; -import java.util.ArrayList; -import java.util.List; - -import com.baeldung.jexcel.JExcelHelper; - -import jxl.write.WriteException; -import jxl.read.biff.BiffException; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import org.junit.Test; -import org.junit.Before; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import jxl.read.biff.BiffException; +import jxl.write.WriteException; public class JExcelIntegrationTest { diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelIntegrationTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelIntegrationTest.java index 5d7ccb9b94..d2fa08e9ea 100644 --- a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelIntegrationTest.java +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelIntegrationTest.java @@ -1,22 +1,15 @@ package com.baeldung.poi.excel; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import jxl.read.biff.BiffException; -import java.util.Map; -import java.util.ArrayList; -import java.util.List; - -import com.baeldung.poi.excel.ExcelPOIHelper; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import org.junit.Test; -import org.junit.Before; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + import org.junit.After; +import org.junit.Before; +import org.junit.Test; public class ExcelIntegrationTest { diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java new file mode 100644 index 0000000000..b4d3fdd732 --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.poi.excel; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import org.junit.Before; +import org.junit.Test; + +public class ExcelUtilityUnitTest { + private static final String FILE_NAME = "baeldung.xlsx"; + private String fileLocation; + private static final String ENDLINE = System.getProperty("line.separator"); + private StringBuilder output; + + @Before + public void setupUnitTest() throws IOException, URISyntaxException, ParseException { + output = new StringBuilder(); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("Worksheet :Sheet1") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("|| Name1 | Surname1 | 3.55696564113E11 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021") + .toString()) + .append(" | ‡ | ||") + .append(ENDLINE); + output.append("|| Name2 | Surname2 | 5.646513512E9 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/12/2021") + .toString()) + .append(" | false | ||") + .append(ENDLINE); + output.append("|| Name3 | Surname3 | 3.55696564113E11 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021") + .toString()) + .append(" | 7.17039641738E11 | ||") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("Worksheet :Sheet2") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("|| Name4 | Surname4 | 3.55675623232E11 | 13/04/2021 | ||") + .append(ENDLINE); + + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME) + .toURI()) + .toString(); + } + + @Test + public void givenStringPath_whenReadExcel_thenReturnStringValue() throws IOException { + assertEquals(output.toString(), ExcelUtility.readExcel(fileLocation)); + + } + + @Test + public void givenStringPath_whenReadExcel_thenThrowException() { + assertThrows(IOException.class, () -> { + ExcelUtility.readExcel("baeldung"); + }); + } + +} diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java.orig b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java.orig new file mode 100644 index 0000000000..cfc3062b5a --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelUtilityUnitTest.java.orig @@ -0,0 +1,112 @@ +package com.baeldung.poi.excel; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import org.junit.Before; +import org.junit.Test; + +public class ExcelUtilityUnitTest { +<<<<<<< HEAD + private static final String FILE_NAME = "baeldung.xlsx"; + private String fileLocation; + private static final String ENDLINE = System.getProperty("line.separator"); + private StringBuilder output; + + @Before + public void setupUnitTest() throws IOException, URISyntaxException, ParseException { + output = new StringBuilder(); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("Worksheet :Sheet1") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("|| Name1 | Surname1 | 3.55696564113E11 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021") + .toString()) + .append(" | ‡ | ||") + .append(ENDLINE); + output.append("|| Name2 | Surname2 | 5.646513512E9 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/12/2021") + .toString()) + .append(" | false | ||") + .append(ENDLINE); + output.append("|| Name3 | Surname3 | 3.55696564113E11 | ") + .append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021") + .toString()) + .append(" | 7.17039641738E11 | ||") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("Worksheet :Sheet2") + .append(ENDLINE); + output.append("--------------------------------------------------------------------") + .append(ENDLINE); + output.append("|| Name4 | Surname4 | 3.55675623232E11 | 13/04/2021 | ||") + .append(ENDLINE); + + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME) + .toURI()) + .toString(); + } + + @Test + public void givenStringPath_whenReadExcel_thenReturnStringValue() throws IOException { + assertEquals(output.toString(), ExcelUtility.readExcel(fileLocation)); + + } + + @Test + public void givenStringPath_whenReadExcel_thenThrowException() { + assertThrows(IOException.class, () -> { + ExcelUtility.readExcel("baeldung"); + }); + } +======= + private static final String FILE_NAME = "baeldung.xlsx"; + private String fileLocation; + private static final String ENDLINE = System.getProperty("line.separator"); + private StringBuilder output; + + @Before + public void setupUnitTest() throws IOException, URISyntaxException, ParseException { + output = new StringBuilder(); + output.append("--------------------------------------------------------------------").append(ENDLINE); + output.append("Worksheet :Sheet1").append(ENDLINE); + output.append("--------------------------------------------------------------------").append(ENDLINE); + output.append("|| Name1 | Surname1 | 3.55696564113E11 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021").toString()).append(" | ‡ | ||") + .append(ENDLINE); + output.append("|| Name2 | Surname2 | 5.646513512E9 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/12/2021").toString()).append(" | false | ||") + .append(ENDLINE); + output.append("|| Name3 | Surname3 | 3.55696564113E11 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021").toString()).append(" | 7.17039641738E11 | ||") + .append(ENDLINE); + output.append("--------------------------------------------------------------------").append(ENDLINE); + output.append("Worksheet :Sheet2").append(ENDLINE); + output.append("--------------------------------------------------------------------").append(ENDLINE); + output.append("|| Name4 | Surname4 | 3.55675623232E11 | 13/04/2021 | ||").append(ENDLINE); + + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString(); + } + + @Test + public void givenStringPath_whenReadExcel_thenReturnStringValue() throws IOException { + assertEquals(output.toString(), ExcelUtility.readExcel(fileLocation)); + + } + + @Test + public void givenStringPath_whenReadExcel_thenThrowException() { + assertThrows(IOException.class, () -> { + ExcelUtility.readExcel("baeldung"); + }); + } +>>>>>>> master + +} diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellBorderHandlerUnitTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellBorderHandlerUnitTest.java new file mode 100644 index 0000000000..2a36a6b1b2 --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellBorderHandlerUnitTest.java @@ -0,0 +1,130 @@ +package com.baeldung.poi.excel.cellstyle; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.*; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + +public class CellBorderHandlerUnitTest { + private static final String FILE_NAME = "cellstyle/CellStyleBorderHandlerTest.xlsx"; + private static final int SHEET_INDEX = 0; + + private static CellBordersHandler cellBordersHandler; + private static Workbook workbook; + + @BeforeClass + public static void setup() throws URISyntaxException, IOException { + String fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString(); + cellBordersHandler = new CellBordersHandler(); + workbook = new XSSFWorkbook(fileLocation); + createRowsAndCells(workbook); + } + + private static void createRowsAndCells(Workbook workbook) { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + for (int rowIndex = 0; rowIndex < 10; rowIndex++) { + Row row = sheet.getRow(rowIndex); + if (row == null) { + row = sheet.createRow(rowIndex); + } + for (int colIndex = 0; colIndex < 10; colIndex++) { + Cell cell = row.getCell(colIndex); + if (cell == null) { + row.createCell(colIndex); + } + } + } + } + + @Test + public void givenWorkbookCell_whenSetRegionBorder() { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + + CellRangeAddress region = new CellRangeAddress(1, 1, 1, 1); + cellBordersHandler.setRegionBorder(region, sheet, BorderStyle.THICK); + + Row row = sheet.getRow(1); + Cell cell = row.getCell(1); + assertEquals(cell.getCellStyle().getBorderTop(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderBottom(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderLeft(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderRight(), BorderStyle.THICK); + } + + @Test + public void givenWorkbookCell_whenSetRegionBorderWithColor() { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + + CellRangeAddress region = new CellRangeAddress(1, 1, 3, 3); + cellBordersHandler.setRegionBorderWithColor(region, sheet, BorderStyle.THICK, IndexedColors.MAROON.index); + + Row row = sheet.getRow(1); + Cell cell = row.getCell(1 + 2); + assertEquals(cell.getCellStyle().getBorderTop(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderBottom(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderLeft(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getBorderRight(), BorderStyle.THICK); + assertEquals(cell.getCellStyle().getTopBorderColor(), IndexedColors.MAROON.index); + assertEquals(cell.getCellStyle().getBottomBorderColor(), IndexedColors.MAROON.index); + assertEquals(cell.getCellStyle().getLeftBorderColor(), IndexedColors.MAROON.index); + assertEquals(cell.getCellStyle().getRightBorderColor(), IndexedColors.MAROON.index); + } + + @Test + public void givenWorkbookCell_whenSetCrazyBorder() { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + + CellRangeAddress region = new CellRangeAddress(1, 1, 5, 5); + cellBordersHandler.setCrazyBorder(region, sheet); + + Row row = sheet.getRow(1); + Cell cell = row.getCell(5); + assertEquals(cell.getCellStyle().getBorderTop(), BorderStyle.DASH_DOT); + assertEquals(cell.getCellStyle().getBorderBottom(), BorderStyle.DOUBLE); + assertEquals(cell.getCellStyle().getBorderLeft(), BorderStyle.DOTTED); + assertEquals(cell.getCellStyle().getBorderRight(), BorderStyle.SLANTED_DASH_DOT); + assertEquals(cell.getCellStyle().getTopBorderColor(), IndexedColors.RED.index); + assertEquals(cell.getCellStyle().getBottomBorderColor(), IndexedColors.GREEN.index); + assertEquals(cell.getCellStyle().getLeftBorderColor(), IndexedColors.BLUE.index); + assertEquals(cell.getCellStyle().getRightBorderColor(), IndexedColors.VIOLET.index); + } + + @Test + public void givenWorkbookRegion_whenSetRegionBorder() { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + + CellRangeAddress region = new CellRangeAddress(3, 5, 1, 5); + cellBordersHandler.setRegionBorder(region, sheet, BorderStyle.MEDIUM); + + Row row = sheet.getRow(3); + Cell cell = row.getCell(1); + assertEquals(cell.getCellStyle().getBorderTop(), BorderStyle.MEDIUM); + assertEquals(cell.getCellStyle().getBorderLeft(), BorderStyle.MEDIUM); + } + + @Test + public void givenWorkbookRegion_whenSetRegionBorderWithColor() { + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + + CellRangeAddress region = new CellRangeAddress(7, 8, 1, 5); + cellBordersHandler.setRegionBorderWithColor(region, sheet, BorderStyle.MEDIUM, IndexedColors.ORANGE.index); + + Row row = sheet.getRow(7); + Cell cell = row.getCell(1); + assertEquals(cell.getCellStyle().getBorderTop(), BorderStyle.MEDIUM); + assertEquals(cell.getCellStyle().getBorderLeft(), BorderStyle.MEDIUM); + assertEquals(cell.getCellStyle().getTopBorderColor(), IndexedColors.ORANGE.index); + assertEquals(cell.getCellStyle().getLeftBorderColor(), IndexedColors.ORANGE.index); + } + + @AfterClass + public static void close() throws IOException { + workbook.close(); + } +} diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStyleHandlerUnitTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStyleHandlerUnitTest.java new file mode 100644 index 0000000000..1aa6445511 --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStyleHandlerUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.poi.excel.cellstyle; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Before; +import org.junit.Test; + +public class CellStyleHandlerUnitTest { + private static final String FILE_NAME = "cellstyle/CellStyleHandlerTest.xlsx"; + private static final int SHEET_INDEX = 0; + private static final int ROW_INDEX = 0; + private static final int CELL_INDEX = 0; + + private String fileLocation; + private CellStyleHandler cellStyleHandler; + + @Before + public void setup() throws URISyntaxException { + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString(); + cellStyleHandler = new CellStyleHandler(); + } + + @Test + public void givenWorkbookCell_whenChangeCellBackgroundColor() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + Row row = sheet.getRow(ROW_INDEX); + Cell cell = row.getCell(CELL_INDEX); + + cellStyleHandler.changeCellBackgroundColor(cell); + + assertEquals(IndexedColors.LIGHT_BLUE.index, cell.getCellStyle().getFillForegroundColor()); + workbook.close(); + } + + @Test + public void givenWorkbookCell_whenChangeCellBackgroundColorWithPattern() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(SHEET_INDEX); + Row row = sheet.getRow(ROW_INDEX); + Cell cell = row.getCell(CELL_INDEX + 1); + + cellStyleHandler.changeCellBackgroundColorWithPattern(cell); + + assertEquals(IndexedColors.LIGHT_BLUE.index, cell.getCellStyle().getFillForegroundColor()); + workbook.close(); + } +} diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStylerUnitTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStylerUnitTest.java new file mode 100644 index 0000000000..074e51919a --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/cellstyle/CellStylerUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.poi.excel.cellstyle; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Before; +import org.junit.Test; + +public class CellStylerUnitTest { + private static String FILE_NAME = "com/baeldung/poi/excel/cellstyle/CellStyle.xlsx"; + private static final String NEW_FILE_NAME = "CellStyleTest_output.xlsx"; + private String fileLocation; + + @Before + public void setup() throws IOException, URISyntaxException { + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME) + .toURI()) + .toString(); + } + + @Test + public void testApplyWarningColor() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(0); + Row row1 = sheet.createRow(0); + row1.setHeightInPoints((short) 40); + + CellStyler styler = new CellStyler(); + CellStyle style = styler.createWarningColor(workbook); + + Cell cell1 = row1.createCell(0); + cell1.setCellStyle(style); + cell1.setCellValue("Hello"); + + Cell cell2 = row1.createCell(1); + cell2.setCellStyle(style); + cell2.setCellValue("world!"); + + FileOutputStream outputStream = new FileOutputStream(NEW_FILE_NAME); + workbook.write(outputStream); + outputStream.close(); + workbook.close(); + } +} diff --git a/apache-poi/src/test/resources/baeldung.xlsx b/apache-poi/src/test/resources/baeldung.xlsx new file mode 100644 index 0000000000..a6ed6c4e6a Binary files /dev/null and b/apache-poi/src/test/resources/baeldung.xlsx differ diff --git a/apache-shiro/pom.xml b/apache-shiro/pom.xml index 325a9939b9..850653ef98 100644 --- a/apache-shiro/pom.xml +++ b/apache-shiro/pom.xml @@ -47,7 +47,7 @@ 1.5.3 - 1.2.17 + 2.17.1 \ No newline at end of file diff --git a/guest/remote-debugging/src/main/resources/logback.xml b/apache-shiro/src/main/resources/logback.xml similarity index 100% rename from guest/remote-debugging/src/main/resources/logback.xml rename to apache-shiro/src/main/resources/logback.xml diff --git a/apache-shiro/src/test/resources/logback-test.xml b/apache-shiro/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/apache-shiro/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java b/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java index 4b2d9e1127..01e7d3adfc 100644 --- a/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java +++ b/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java @@ -1,9 +1,9 @@ package com.baeldung.differences.rdd; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaRDD; @@ -12,12 +12,15 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.File; + public class TransformationsUnitTest { - + public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; + private static JavaSparkContext sc; private static JavaRDD tourists; - + @BeforeClass public static void init() { SparkConf conf = new SparkConf().setAppName("uppercaseCountries") @@ -25,8 +28,11 @@ public class TransformationsUnitTest { sc = new JavaSparkContext(conf); tourists = sc.textFile("data/Tourist.csv") .filter(line -> !line.startsWith("Region")); //filter header row + + // delete previous output dir and files + FileUtils.deleteQuietly(new File("data/output")); } - + @AfterClass public static void cleanup() { sc.close(); @@ -39,9 +45,9 @@ public class TransformationsUnitTest { return columns[1].toUpperCase(); }) .distinct(); - + upperCaseCountries.saveAsTextFile("data/output/uppercase.txt"); - + upperCaseCountries.foreach(country -> { //replace non alphanumerical characters country = country.replaceAll("[^a-zA-Z]", ""); @@ -52,9 +58,9 @@ public class TransformationsUnitTest { @Test public void whenFilterByCountry_thenShowRequestedCountryRecords() { JavaRDD touristsInMexico = tourists.filter(line -> line.split(COMMA_DELIMITER)[1].equals("Mexico")); - + touristsInMexico.saveAsTextFile("data/output/touristInMexico.txt"); - + touristsInMexico.foreach(record -> { assertEquals("Mexico", record.split(COMMA_DELIMITER)[1]); }); diff --git a/atomikos/pom.xml b/atomikos/pom.xml index cb10168c0d..cd798825d1 100644 --- a/atomikos/pom.xml +++ b/atomikos/pom.xml @@ -71,12 +71,6 @@ derby ${derby.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - javax.transaction diff --git a/aws-lambda/lambda/pom.xml b/aws-lambda/lambda/pom.xml index dea951d1b3..8bfe7a0ade 100644 --- a/aws-lambda/lambda/pom.xml +++ b/aws-lambda/lambda/pom.xml @@ -10,9 +10,8 @@ com.baeldung - parent-modules + aws-lambda 1.0.0-SNAPSHOT - ../../ @@ -63,7 +62,8 @@ json-simple ${json-simple.version} - + junit junit diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index 3264356977..fc655f282d 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -11,7 +11,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../ diff --git a/aws-lambda/shipping-tracker/ShippingFunction/pom.xml b/aws-lambda/shipping-tracker/ShippingFunction/pom.xml index 72e3ac7959..51e9cb9bd3 100644 --- a/aws-lambda/shipping-tracker/ShippingFunction/pom.xml +++ b/aws-lambda/shipping-tracker/ShippingFunction/pom.xml @@ -5,8 +5,8 @@ com.baeldung ShippingFunction 1.0 - jar ShippingFunction + jar diff --git a/aws-lambda/todo-reminder/ToDoFunction/pom.xml b/aws-lambda/todo-reminder/ToDoFunction/pom.xml index c17ff8bf15..cb6dd08d1e 100644 --- a/aws-lambda/todo-reminder/ToDoFunction/pom.xml +++ b/aws-lambda/todo-reminder/ToDoFunction/pom.xml @@ -5,8 +5,8 @@ helloworld ToDoFunction 1.0 - jar ToDoFunction + jar @@ -111,7 +111,7 @@ 11.2 5.0.1 1.2.0 - 3.3.0 + 4.1.0 3.19.0 5.8.1 diff --git a/aws/pom.xml b/aws/pom.xml index 1663266612..a57dd6690e 100644 --- a/aws/pom.xml +++ b/aws/pom.xml @@ -20,18 +20,6 @@ aws-java-sdk ${aws-java-sdk.version} - - org.mockito - mockito-core - ${mockito-core.version} - test - - - org.assertj - assertj-core - ${assertj-core.version} - test - com.amazonaws aws-lambda-java-core @@ -117,8 +105,6 @@ 1.1.0 2.8.0 1.11.290 - 2.21.0 - 3.8.0 1.11.86 https://s3-us-west-2.amazonaws.com/dynamodb-local/release 1.10.L001 diff --git a/axon/pom.xml b/axon/pom.xml index 426c340bfc..00e3f0f4c5 100644 --- a/axon/pom.xml +++ b/axon/pom.xml @@ -19,7 +19,7 @@ org.axonframework axon-bom - 4.5.0 + ${axon.version} pom import @@ -56,4 +56,8 @@ + + 4.5.0 + + \ No newline at end of file diff --git a/blade/pom.xml b/blade/pom.xml index 8fc517e966..9c8638f0bc 100644 --- a/blade/pom.xml +++ b/blade/pom.xml @@ -36,12 +36,6 @@ provided - - org.assertj - assertj-core - ${assertj-core.version} - test - org.apache.httpcomponents httpclient @@ -119,7 +113,6 @@ 4.5.6 4.5.6 4.4.10 - 3.11.1 3.0.0-M3 0.7 3.1.0 diff --git a/cdi/pom.xml b/cdi/pom.xml index 5eb566dcfb..ee23e082c7 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -25,12 +25,6 @@ weld-se-core ${weld-se-core.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - org.aspectj aspectjweaver @@ -53,7 +47,6 @@ 2.0.SP1 3.0.5.Final 1.9.2 - 3.10.0 \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml index 74603bf0fb..7fcce181a3 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml @@ -10,9 +10,8 @@ com.baeldung - parent-boot-2 + cloud-foundry-uaa 0.0.1-SNAPSHOT - ../../parent-boot-2 diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml index 276c8bbaa6..4dffd4d768 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml @@ -10,9 +10,8 @@ com.baeldung - parent-boot-2 + cloud-foundry-uaa 0.0.1-SNAPSHOT - ../../parent-boot-2 diff --git a/cloud-foundry-uaa/pom.xml b/cloud-foundry-uaa/pom.xml index 03a5b978d4..6ae43b2c08 100644 --- a/cloud-foundry-uaa/pom.xml +++ b/cloud-foundry-uaa/pom.xml @@ -4,14 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 cloud-foundry-uaa - 0.0.1-SNAPSHOT cloud-foundry-uaa pom com.baeldung - parent-modules - 1.0.0-SNAPSHOT + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 diff --git a/core-java-modules/core-java-10/pom.xml b/core-java-modules/core-java-10/pom.xml index b293110546..e2ac8db919 100644 --- a/core-java-modules/core-java-10/pom.xml +++ b/core-java-modules/core-java-10/pom.xml @@ -12,7 +12,6 @@ com.baeldung.core-java-modules core-java-modules 0.0.1-SNAPSHOT - ../ @@ -40,7 +39,6 @@ 10 10 - 4.1 \ No newline at end of file diff --git a/core-java-modules/core-java-11-2/README.md b/core-java-modules/core-java-11-2/README.md index 93920864cc..2b0eda8d91 100644 --- a/core-java-modules/core-java-11-2/README.md +++ b/core-java-modules/core-java-11-2/README.md @@ -9,3 +9,5 @@ This module contains articles about Java 11 core features - [New Features in Java 11](https://www.baeldung.com/java-11-new-features) - [Getting the Java Version at Runtime](https://www.baeldung.com/get-java-version-runtime) - [Invoking a SOAP Web Service in Java](https://www.baeldung.com/java-soap-web-service) +- [Java HTTPS Client Certificate Authentication](https://www.baeldung.com/java-https-client-certificate-authentication) +- [Call Methods at Runtime Using Java Reflection](https://www.baeldung.com/java-method-reflection) diff --git a/core-java-modules/core-java-11-2/pom.xml b/core-java-modules/core-java-11-2/pom.xml index 68e8b66d67..64a486b5c4 100644 --- a/core-java-modules/core-java-11-2/pom.xml +++ b/core-java-modules/core-java-11-2/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../.. + ../../pom.xml @@ -21,35 +21,11 @@ guava ${guava.version} - - org.assertj - assertj-core - ${assertj.version} - test - org.mock-server mockserver-junit-jupiter ${mockserver.version} - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-params - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - org.apache.commons commons-lang3 @@ -60,18 +36,6 @@ jakarta.xml.ws-api ${jakarta.ws-api.version} - - com.sun.xml.ws - jaxws-rt - ${jaxws-rt.version} - runtime - - - com.sun.xml.ws - jaxws-ri - ${jaxws-ri.version} - pom - @@ -105,14 +69,9 @@ 11 11 - 29.0-jre - 3.17.2 5.11.1 - 3.12.0 - 3.0.0 - 3.0.0 - 2.3.1 - 2.3.2 + 3.0.1 + 3.0.2 \ No newline at end of file diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLScocketClient.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLScocketClient.java new file mode 100644 index 0000000000..286ecfc9df --- /dev/null +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLScocketClient.java @@ -0,0 +1,41 @@ +package com.baeldung.httpsclientauthentication; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +public class SSLScocketClient { + + static void startClient(String host, int port) throws IOException { + + SocketFactory factory = SSLSocketFactory.getDefault(); + + try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) { + socket.setEnabledCipherSuites(new String[] { "TLS_AES_128_GCM_SHA256" }); + socket.setEnabledProtocols(new String[] { "TLSv1.3" }); + InputStream is = new BufferedInputStream(socket.getInputStream()); + String message = "Hello World Message"; + System.out.println("sending message: " + message); + OutputStream os = new BufferedOutputStream(socket.getOutputStream()); + os.write(message.getBytes()); + os.flush(); + byte[] data = new byte[2048]; + int len = is.read(data); + if (len <= 0) { + throw new IOException("no data received"); + } + System.out.printf("client received %d bytes: %s%n", len, new String(data, 0, len)); + } + } + + public static void main(String[] args) throws IOException { + + startClient("localhost", 8443); + } +} diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLSocketEchoServer.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLSocketEchoServer.java new file mode 100644 index 0000000000..66efa18fe9 --- /dev/null +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/httpsclientauthentication/SSLSocketEchoServer.java @@ -0,0 +1,46 @@ +package com.baeldung.httpsclientauthentication; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + +public class SSLSocketEchoServer { + + static void startServer(int port) throws IOException { + + ServerSocketFactory factory = SSLServerSocketFactory.getDefault(); + + try (SSLServerSocket listener = (SSLServerSocket) factory.createServerSocket(port)) { + listener.setNeedClientAuth(true); + listener.setEnabledCipherSuites(new String[] { "TLS_AES_128_GCM_SHA256" }); + listener.setEnabledProtocols(new String[] { "TLSv1.3" }); + System.out.println("listening for messages..."); + try (Socket socket = listener.accept()) { + InputStream is = new BufferedInputStream(socket.getInputStream()); + OutputStream os = new BufferedOutputStream(socket.getOutputStream()); + byte[] data = new byte[2048]; + int len = is.read(data); + if (len <= 0) { + throw new IOException("no data received"); + } + String message = new String(data, 0, len); + System.out.printf("server received %d bytes: %s%n", len, message); + String response = message + " processed by server"; + os.write(response.getBytes(), 0, response.getBytes().length); + os.flush(); + } + System.out.println("message processed, exiting"); + } + } + + public static void main(String[] args) throws IOException { + startServer(8443); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Country.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Country.java index 950d588661..d39f333b41 100644 --- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Country.java +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Country.java @@ -1,10 +1,10 @@ package com.baeldung.soap.ws.client.generated; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; /** diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java index 807d152cf1..f10dcade1b 100644 --- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java @@ -1,19 +1,19 @@ package com.baeldung.soap.ws.client.generated; -import javax.jws.WebMethod; -import javax.jws.WebParam; -import javax.jws.WebResult; -import javax.jws.WebService; -import javax.jws.soap.SOAPBinding; -import javax.xml.bind.annotation.XmlSeeAlso; -import javax.xml.ws.Action; +import jakarta.jws.WebMethod; +import jakarta.jws.WebParam; +import jakarta.jws.WebResult; +import jakarta.jws.WebService; +import jakarta.jws.soap.SOAPBinding; +import jakarta.xml.bind.annotation.XmlSeeAlso; +import jakarta.xml.ws.Action; /** * This class was generated by the JAX-WS RI. - * JAX-WS RI 2.3.2 - * Generated source version: 2.2 + * JAX-WS RI 3.0.2 + * Generated source version: 3.0 * */ @WebService(name = "CountryService", targetNamespace = "http://server.ws.soap.baeldung.com/") diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java index 97d6c82145..ae7ff38f7d 100644 --- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java @@ -4,17 +4,17 @@ package com.baeldung.soap.ws.client.generated; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; -import javax.xml.ws.Service; -import javax.xml.ws.WebEndpoint; -import javax.xml.ws.WebServiceClient; -import javax.xml.ws.WebServiceException; -import javax.xml.ws.WebServiceFeature; +import jakarta.xml.ws.Service; +import jakarta.xml.ws.WebEndpoint; +import jakarta.xml.ws.WebServiceClient; +import jakarta.xml.ws.WebServiceException; +import jakarta.xml.ws.WebServiceFeature; /** * This class was generated by the JAX-WS RI. - * JAX-WS RI 2.3.2 - * Generated source version: 2.2 + * JAX-WS RI 3.0.2 + * Generated source version: 3.0 * */ @WebServiceClient(name = "CountryServiceImplService", targetNamespace = "http://server.ws.soap.baeldung.com/", wsdlLocation = "http://localhost:8888/ws/country?wsdl") @@ -75,7 +75,7 @@ public class CountryServiceImplService /** * * @param features - * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. + * A list of {@link jakarta.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. * @return * returns CountryService */ diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java index c010f5533c..ad42c65461 100644 --- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java @@ -1,15 +1,14 @@ package com.baeldung.soap.ws.client.generated; -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlEnum; +import jakarta.xml.bind.annotation.XmlType; /** *

Java class for currency. * *

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

*

  * <simpleType name="currency">
  *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java
index 9ed85fe2b9..0489e49c2b 100644
--- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java
+++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java
@@ -1,7 +1,7 @@
 
 package com.baeldung.soap.ws.client.generated;
 
-import javax.xml.bind.annotation.XmlRegistry;
+import jakarta.xml.bind.annotation.XmlRegistry;
 
 
 /**
diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java
index dfc556859f..6dcc08c268 100644
--- a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java
+++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java
@@ -1,2 +1,2 @@
-@javax.xml.bind.annotation.XmlSchema(namespace = "http://server.ws.soap.baeldung.com/")
+@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://server.ws.soap.baeldung.com/")
 package com.baeldung.soap.ws.client.generated;
diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/reflection/OperationsUnitTest.java b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/reflection/OperationsUnitTest.java
index 7584d5da94..92f5b83f2b 100644
--- a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/reflection/OperationsUnitTest.java
+++ b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/reflection/OperationsUnitTest.java
@@ -2,6 +2,7 @@ package com.baeldung.reflection;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertThat;
 
 import java.lang.reflect.InvocationTargetException;
@@ -34,6 +35,25 @@ public class OperationsUnitTest {
 
         assertFalse(result);
     }
+    
+    @Test
+    public void givenObject_whenInvokePrivateMethod_thenCheckAccess() throws Exception {
+        Operations operationsInstance = new Operations();
+        Method andPrivatedMethod = Operations.class.getDeclaredMethod("privateAnd", boolean.class, boolean.class);
+        boolean isAccessEnabled = andPrivatedMethod.canAccess(operationsInstance);
+        
+        assertFalse(isAccessEnabled);
+    }
+    
+    @Test
+    public void givenObject_whenInvokePublicMethod_thenEnableAccess() throws Exception {
+        Operations operationsInstance = new Operations();
+        Method andPrivatedMethod = Operations.class.getDeclaredMethod("privateAnd", boolean.class, boolean.class);
+        andPrivatedMethod.trySetAccessible();
+        boolean isAccessEnabled = andPrivatedMethod.canAccess(operationsInstance);
+        
+        assertTrue(isAccessEnabled);
+    }
 
     @Test
     public void givenObject_whenInvokePublicMethod_thenCorrect() throws Exception {
diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionUnitTest.java b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionManualTest.java
similarity index 92%
rename from core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionUnitTest.java
rename to core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionManualTest.java
index 128c7f60f4..74035a3e2f 100644
--- a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionUnitTest.java
+++ b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/version/VersionManualTest.java
@@ -5,7 +5,8 @@ import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
-public class VersionUnitTest {
+// manual test as the runtime JDK version can be different depending on where the test is run
+public class VersionManualTest {
 
     @Test
     public void givenJava_whenUsingRuntime_thenGetVersion() {
diff --git a/core-java-modules/core-java-11/pom.xml b/core-java-modules/core-java-11/pom.xml
index def7ab43f7..28a218c400 100644
--- a/core-java-modules/core-java-11/pom.xml
+++ b/core-java-modules/core-java-11/pom.xml
@@ -13,7 +13,7 @@
         com.baeldung
         parent-modules
         1.0.0-SNAPSHOT
-        ../..
+        ../../pom.xml
     
 
     
@@ -22,12 +22,6 @@
             guava
             ${guava.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.openjdk.jmh
             jmh-core
@@ -103,8 +97,6 @@
     
         11
         11
-        27.1-jre
-        3.11.1
         benchmarks
         10.0.0
         3.2.4
diff --git a/core-java-modules/core-java-12/pom.xml b/core-java-modules/core-java-12/pom.xml
index 931fce820b..9f95b1bc3f 100644
--- a/core-java-modules/core-java-12/pom.xml
+++ b/core-java-modules/core-java-12/pom.xml
@@ -13,20 +13,13 @@
         com.baeldung
         parent-modules
         1.0.0-SNAPSHOT
-        ../../
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             commons-io
             commons-io
-            2.11.0
+            ${commons-io.version}
         
     
 
@@ -54,7 +47,6 @@
     
         12
         12
-        3.6.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-13/pom.xml b/core-java-modules/core-java-13/pom.xml
index 6369976580..9e42838971 100644
--- a/core-java-modules/core-java-13/pom.xml
+++ b/core-java-modules/core-java-13/pom.xml
@@ -14,18 +14,8 @@
         com.baeldung
         parent-modules
         1.0.0-SNAPSHOT
-        ../../
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-    
-
     
         
             
@@ -53,7 +43,6 @@
     
         13
         13
-        3.6.1
         3.0.0-M3
     
 
diff --git a/core-java-modules/core-java-14/pom.xml b/core-java-modules/core-java-14/pom.xml
index a03332d8bc..35ea0bd2d0 100644
--- a/core-java-modules/core-java-14/pom.xml
+++ b/core-java-modules/core-java-14/pom.xml
@@ -12,30 +12,8 @@
         com.baeldung
         parent-modules
         1.0.0-SNAPSHOT
-        ../../
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-engine
-            ${junit-jupiter.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-api
-            ${junit-jupiter.version}
-            test
-        
-    
-
     
         
             
@@ -62,7 +40,6 @@
 
     
         14
-        3.6.1
         3.8.1
         3.0.0-M3
     
diff --git a/core-java-modules/core-java-15/README.md b/core-java-modules/core-java-15/README.md
index de503fbb31..4b163fcfb5 100644
--- a/core-java-modules/core-java-15/README.md
+++ b/core-java-modules/core-java-15/README.md
@@ -4,4 +4,5 @@ This module contains articles about Java 15.
 
 ### Relevant articles
 
+- [Hidden Classes in Java 15](https://www.baeldung.com/java-hidden-classes)
 - [Sealed Classes and Interfaces in Java 15](https://www.baeldung.com/java-sealed-classes-interfaces)
diff --git a/core-java-modules/core-java-15/pom.xml b/core-java-modules/core-java-15/pom.xml
index 091f0568a7..a4923054ac 100644
--- a/core-java-modules/core-java-15/pom.xml
+++ b/core-java-modules/core-java-15/pom.xml
@@ -22,22 +22,9 @@
             ${commons-lang3.version}
         
         
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-engine
-            ${junit-jupiter.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-api
-            ${junit-jupiter.version}
-            test
+            commons-io
+            commons-io
+            ${commons-io.version}
         
     
 
@@ -67,7 +54,6 @@
 
     
         15
-        3.17.2
         3.8.1
         3.0.0-M3
     
diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/hidden/classes/HiddenClass.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/hidden/classes/HiddenClass.java
new file mode 100644
index 0000000000..d90e512b39
--- /dev/null
+++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/hidden/classes/HiddenClass.java
@@ -0,0 +1,7 @@
+package com.baeldung.hidden.classes;
+
+public class HiddenClass {
+    public String convertToUpperCase(String s) {
+        return s.toUpperCase();
+    }
+}
diff --git a/core-java-modules/core-java-15/src/test/java/com/baeldung/hidden/classes/HiddenClassUnitTest.java b/core-java-modules/core-java-15/src/test/java/com/baeldung/hidden/classes/HiddenClassUnitTest.java
new file mode 100644
index 0000000000..ac6670b208
--- /dev/null
+++ b/core-java-modules/core-java-15/src/test/java/com/baeldung/hidden/classes/HiddenClassUnitTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.hidden.classes;
+
+
+import java.io.InputStream;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup.ClassOption;
+import java.lang.reflect.Method;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HiddenClassUnitTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HiddenClassUnitTest.class);
+
+    @Test
+    void whenInvokeMethodOnHiddenClass_thenSuccess() {
+        // Initiate lookup class
+        MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+        // Create a byte code of a class
+
+        Class clazz = HiddenClass.class;
+        String className = clazz.getName();
+        String classAsPath = className.replace('.', '/') + ".class";
+        InputStream stream = clazz.getClassLoader()
+            .getResourceAsStream(classAsPath);
+
+        try {
+            // Define hidden class with byte code
+            Class hiddenClass = lookup.defineHiddenClass(IOUtils.toByteArray(stream), true, ClassOption.NESTMATE)
+                .lookupClass();
+            Object hiddenClassObject = hiddenClass.getConstructor()
+                .newInstance();
+
+            Method method = hiddenClassObject.getClass()
+                .getDeclaredMethod("convertToUpperCase", String.class);
+
+            Assertions.assertEquals(true, hiddenClass.isHidden());
+
+            Assertions.assertEquals("HELLO", method.invoke(hiddenClassObject, "Hello"));
+
+            Assertions.assertEquals(this.getClass()
+                .getClassLoader(), hiddenClass.getClassLoader());
+
+            Assertions.assertEquals(null, hiddenClass.getCanonicalName());      
+            
+            Assertions.assertThrows(ClassNotFoundException.class, () -> Class.forName(hiddenClass.getName()));
+            
+            Assertions.assertThrows(ClassNotFoundException.class, () -> lookup.findClass(hiddenClass.getName()));
+
+        } catch (Exception e) {
+            LOG.error("Couldn't instantiate hidden class" + e);
+        }
+    }
+
+}
diff --git a/core-java-modules/core-java-16/pom.xml b/core-java-modules/core-java-16/pom.xml
index 5d10325f03..4adc3ee6d1 100644
--- a/core-java-modules/core-java-16/pom.xml
+++ b/core-java-modules/core-java-16/pom.xml
@@ -17,29 +17,11 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.apache.commons
             commons-lang3
-            3.12.0
+            ${commons-lang3.version}
         
-		
-			org.junit.jupiter
-			junit-jupiter-engine
-			${junit-jupiter.version}
-			test
-		
-		
-			org.junit.jupiter
-			junit-jupiter-api
-			${junit-jupiter.version}
-			test
-		
     
 
     
@@ -50,37 +32,35 @@
                 ${maven-compiler-plugin.version}
                 
                     ${maven.compiler.release}
-					--enable-preview
+                    --enable-preview
                     ${maven.compiler.source.version}
                     ${maven.compiler.target.version}
                 
             
-			
-				org.apache.maven.plugins
-				maven-surefire-plugin
-				${surefire.plugin.version}
-				
-					--enable-preview
-					1
-				
-				
-					
-						org.apache.maven.surefire
-						surefire-api
-						${surefire.plugin.version}
-					
-				
-			
+            
+                org.apache.maven.plugins
+                maven-surefire-plugin
+                ${surefire.plugin.version}
+                
+                    --enable-preview
+                    1
+                
+                
+                    
+                        org.apache.maven.surefire
+                        surefire-api
+                        ${surefire.plugin.version}
+                    
+                
+            
         
     
 
     
         16
         16
-		16
-		3.8.1
-		3.0.0-M5
-		3.17.2
+        16
+        3.0.0-M5
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/README.md b/core-java-modules/core-java-17/README.md
index 074c5e4f86..1f061bd7c1 100644
--- a/core-java-modules/core-java-17/README.md
+++ b/core-java-modules/core-java-17/README.md
@@ -1,3 +1,7 @@
 ### Relevant articles:
 
+- [An Introduction to InstantSource in Java 17](https://www.baeldung.com/java-instantsource)
 - [Pattern Matching for Switch](https://www.baeldung.com/java-switch-pattern-matching)
+- [Introduction to HexFormat in Java 17](https://www.baeldung.com/java-hexformat)
+- [New Features in Java 17](https://www.baeldung.com/java-17-new-features)
+- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
diff --git a/core-java-modules/core-java-17/pom.xml b/core-java-modules/core-java-17/pom.xml
index f9a7ec326b..bc949d9050 100644
--- a/core-java-modules/core-java-17/pom.xml
+++ b/core-java-modules/core-java-17/pom.xml
@@ -16,27 +16,6 @@
         ../../
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-		
-			org.junit.jupiter
-			junit-jupiter-engine
-			${junit-jupiter.version}
-			test
-		
-		
-			org.junit.jupiter
-			junit-jupiter-api
-			${junit-jupiter.version}
-			test
-		
-    
-
     
         
             
@@ -48,34 +27,54 @@
                     --enable-preview
                     ${maven.compiler.source.version}
                     ${maven.compiler.target.version}
+                    
+                        
+                            org.openjdk.jmh
+                            jmh-generator-annprocess
+                            ${jmh-generator.version}
+                        
+                    
                 
             
-			
-				org.apache.maven.plugins
-				maven-surefire-plugin
-				${surefire.plugin.version}
-				
-					--enable-preview
-					1
-				
-				
-					
-						org.apache.maven.surefire
-						surefire-api
-						${surefire.plugin.version}
-					
-				
-			
+            
+                org.apache.maven.plugins
+                maven-surefire-plugin
+                ${surefire.plugin.version}
+                
+                    --enable-preview
+                    --enable-native-access=core.java
+                    1
+                
+                
+                    
+                        org.apache.maven.surefire
+                        surefire-api
+                        ${surefire.plugin.version}
+                    
+                
+            
         
     
 
+    
+        
+            org.openjdk.jmh
+            jmh-core
+            ${jmh-core.version}
+        
+        
+            org.openjdk.jmh
+            jmh-generator-annprocess
+            ${jmh-generator.version}
+            test
+        
+    
+
     
         17
         17
-		17
-		3.8.1
-		3.0.0-M5
-		3.17.2
+        17
+        3.0.0-M5
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP356.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP356.java
new file mode 100644
index 0000000000..0890b025be
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP356.java
@@ -0,0 +1,20 @@
+package com.baeldung.features;
+
+import java.util.random.RandomGeneratorFactory;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class JEP356 {
+
+    public Stream getAllAlgorithms() {
+        return RandomGeneratorFactory.all().map(RandomGeneratorFactory::name);
+    }
+
+    public IntStream getPseudoInts(String algorithm, int streamSize) {
+        // returns an IntStream with size @streamSize of random numbers generated using the @algorithm
+        // where the lower bound is 0 and the upper is 100 (exclusive)
+        return RandomGeneratorFactory.of(algorithm)
+                .create()
+                .ints(streamSize, 0,100);
+    }
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP406.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP406.java
new file mode 100644
index 0000000000..2bc3a664d1
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP406.java
@@ -0,0 +1,28 @@
+package com.baeldung.features;
+
+import com.baeldung.features.JEP409.Circle;
+import com.baeldung.features.JEP409.Shape;
+import com.baeldung.features.JEP409.Triangle;
+
+public class JEP406 {
+
+    static record Human (String name, int age, String profession) {}
+
+    public String checkObject(Object obj) {
+        return switch (obj) {
+            case Human h -> "Name: %s, age: %s and profession: %s".formatted(h.name(), h.age(), h.profession());
+            case Circle c -> "This is a circle";
+            case Shape s -> "It is just a shape";
+            case null -> "It is null";
+            default -> "It is an object";
+        };
+    }
+
+    public String checkShape(Shape shape) {
+        return switch (shape) {
+            case Triangle t && (t.getNumberOfSides() != 3) -> "This is a weird triangle";
+            case Circle c && (c.getNumberOfSides() != 0) -> "This is a weird circle";
+            default -> "Just a normal shape";
+        };
+    }
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP409.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP409.java
new file mode 100644
index 0000000000..0fc3d6f467
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP409.java
@@ -0,0 +1,38 @@
+package com.baeldung.features;
+
+public class JEP409 {
+
+    sealed interface Shape permits Rectangle, Circle, Square, Triangle {
+        int getNumberOfSides();
+    }
+
+    static final class Rectangle implements Shape {
+        @Override
+        public int getNumberOfSides() {
+            return 4;
+        }
+    }
+
+    static final class Circle implements Shape {
+        @Override
+        public int getNumberOfSides() {
+            return 0;
+        }
+    }
+
+    static final class Square implements Shape {
+        @Override
+        public int getNumberOfSides() {
+            return 4;
+        }
+    }
+
+    static non-sealed class Triangle implements Shape {
+
+        @Override
+        public int getNumberOfSides() {
+            return 3;
+        }
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP412.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP412.java
new file mode 100644
index 0000000000..8c998629c9
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP412.java
@@ -0,0 +1,56 @@
+package com.baeldung.features;
+
+import jdk.incubator.foreign.CLinker;
+import jdk.incubator.foreign.FunctionDescriptor;
+import jdk.incubator.foreign.MemoryAddress;
+import jdk.incubator.foreign.SymbolLookup;
+
+import java.io.IOException;
+import java.lang.invoke.MethodType;
+
+import static jdk.incubator.foreign.ResourceScope.newImplicitScope;
+
+public class JEP412 {
+
+    private static final SymbolLookup libLookup;
+
+    static {
+        var resource = JEP412.class.getResource("/compile_c.sh");
+        try {
+            var process = new ProcessBuilder("sh", resource.getPath()).start();
+            while (process.isAlive()) {}
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        var path = JEP412.class.getResource("/print_name.so").getPath();
+        System.load(path);
+        libLookup = SymbolLookup.loaderLookup();
+    }
+
+    public String getPrintNameFormat(String name){
+
+        var printMethod = libLookup.lookup("printName");
+
+        if (printMethod.isPresent()) {
+            var methodReference = CLinker.getInstance()
+                .downcallHandle(
+                    printMethod.get(),
+                    MethodType.methodType(MemoryAddress.class, MemoryAddress.class),
+                    FunctionDescriptor.of(CLinker.C_POINTER, CLinker.C_POINTER)
+                );
+
+            try {
+                var nativeString = CLinker.toCString(name, newImplicitScope());
+                var invokeReturn = methodReference.invoke(nativeString.address());
+                var memoryAddress = (MemoryAddress) invokeReturn;
+                return CLinker.toJavaString(memoryAddress);
+            } catch (Throwable throwable) {
+                throw new RuntimeException(throwable);
+            }
+        }
+        throw new RuntimeException("printName function not found.");
+    }
+}
+
+
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP414.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP414.java
new file mode 100644
index 0000000000..aaccc4a665
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/features/JEP414.java
@@ -0,0 +1,27 @@
+package com.baeldung.features;
+
+import jdk.incubator.vector.FloatVector;
+import jdk.incubator.vector.VectorSpecies;
+
+public class JEP414 {
+
+    private static final VectorSpecies SPECIES = FloatVector.SPECIES_PREFERRED;
+
+
+    public void newVectorComputation(float[] a, float[] b, float[] c) {
+        for (var i = 0; i < a.length; i += SPECIES.length()) {
+            var m = SPECIES.indexInRange(i, a.length);
+            var va = FloatVector.fromArray(SPECIES, a, i, m);
+            var vb = FloatVector.fromArray(SPECIES, b, i, m);
+            var vc = va.mul(vb);
+            vc.intoArray(c, i, m);
+        }
+    }
+
+    public void commonVectorComputation(float[] a, float[] b, float[] c) {
+        for (var i = 0; i < a.length; i ++) {
+            c[i] = a[i] * b[i];
+        }
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantExample.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantExample.java
new file mode 100644
index 0000000000..0b7fd569f0
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantExample.java
@@ -0,0 +1,21 @@
+package com.baeldung.instantsource;
+
+import java.time.Instant;
+import java.time.InstantSource;
+
+public class InstantExample {
+    InstantWrapper instantWrapper;
+    InstantSource instantSource;
+
+    public InstantExample(InstantWrapper instantWrapper, InstantSource instantSource) {
+        this.instantWrapper = instantWrapper;
+        this.instantSource = instantSource;
+    }
+
+    public Instant getCurrentInstantFromWrapper() {
+        return instantWrapper.instant();
+    }
+    public Instant getCurrentInstantFromInstantSource() {
+        return instantSource.instant();
+    }
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantWrapper.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantWrapper.java
new file mode 100644
index 0000000000..d88a8b5a8a
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/instantsource/InstantWrapper.java
@@ -0,0 +1,39 @@
+package com.baeldung.instantsource;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+public class InstantWrapper {
+    Clock clock;
+
+    private InstantWrapper() {
+        this.clock = Clock.systemDefaultZone();
+    }
+
+    private InstantWrapper(ZonedDateTime zonedDateTime) {
+        this.clock = Clock.fixed(zonedDateTime.toInstant(), zonedDateTime.getZone());
+    }
+
+    private InstantWrapper(LocalDateTime localDateTime) {
+        this.clock = Clock.fixed(localDateTime.toInstant(ZoneOffset.UTC), ZoneOffset.UTC);
+    }
+
+    public static InstantWrapper of() {
+        return new InstantWrapper();
+    }
+
+    public static InstantWrapper of(ZonedDateTime zonedDateTime) {
+        return new InstantWrapper(zonedDateTime);
+    }
+
+    public static InstantWrapper of(LocalDateTime localDateTime) {
+        return new InstantWrapper(localDateTime);
+    }
+
+    public Instant instant() {
+        return clock.instant();
+    }
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java
new file mode 100644
index 0000000000..9a40a2de4e
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java
@@ -0,0 +1,115 @@
+package com.baeldung.randomgenerators;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+
+import java.util.concurrent.TimeUnit;
+import java.util.random.RandomGenerator;
+
+public class BenchmarkRunner {
+
+    public static void main(String[] args) throws Exception {
+        org.openjdk.jmh.Main.main(args);
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL128X1024MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L128X1024MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL128X128MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L128X128MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL128X256MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L128X256MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL32X64MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L32X64MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL64X1024MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L64X1024MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL64X128MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L64X128MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL64X128StarStarRandom() {
+        generateRandomNumbers(RandomGenerator.of("L64X128StarStarRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testL64X256MixRandom() {
+        generateRandomNumbers(RandomGenerator.of("L64X256MixRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testRandom() {
+        generateRandomNumbers(RandomGenerator.of("Random"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testSecureRandom() {
+        generateRandomNumbers(RandomGenerator.of("SecureRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testSplittableRandom() {
+        generateRandomNumbers(RandomGenerator.of("SplittableRandom"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testXoroshiro128PlusPlus() {
+        generateRandomNumbers(RandomGenerator.of("Xoroshiro128PlusPlus"));
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.AverageTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public static void testXoshiro256PlusPlus() {
+        generateRandomNumbers(RandomGenerator.of("Xoshiro256PlusPlus"));
+    }
+
+    private static void generateRandomNumbers(RandomGenerator generator) {
+        generator.nextLong();
+        generator.nextInt();
+        generator.nextFloat();
+        generator.nextDouble();
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java
new file mode 100644
index 0000000000..64bc81a035
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java
@@ -0,0 +1,36 @@
+package com.baeldung.randomgenerators;
+
+import java.util.Comparator;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGeneratorFactory;
+
+public class GeneratorFactory {
+
+    public static void main(String[] args) {
+        System.out.println("Group\tName\tJumpable?\tSplittable?");
+        RandomGeneratorFactory.all()
+          .sorted(Comparator.comparing(RandomGeneratorFactory::name))
+          .forEach(factory -> System.out.println(String.format("%s\t%s\t%s\t%s",
+            factory.group(),
+            factory.name(),
+            factory.isJumpable(),
+            factory.isSplittable())));
+    }
+
+    public static int getRandomInt(RandomGenerator generator, int bound) {
+        return generator.nextInt(bound);
+    }
+
+    public static RandomGenerator getDefaultGenerator() {
+        return RandomGeneratorFactory.getDefault().create();
+    }
+
+    public static RandomGenerator getJumpableGenerator() {
+        return RandomGeneratorFactory.all()
+          .filter(RandomGeneratorFactory::isJumpable)
+          .findAny()
+          .map(RandomGeneratorFactory::create)
+          .orElseThrow(() -> new RuntimeException("Error creating a generator"));
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java
new file mode 100644
index 0000000000..c84d5bc8d3
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java
@@ -0,0 +1,12 @@
+package com.baeldung.randomgenerators;
+
+import java.util.Random;
+
+public class OldRandom {
+
+    public static int getRandomInt(int bound) {
+        Random random = new Random();
+        return random.nextInt(bound);
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java
new file mode 100644
index 0000000000..298d840da9
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java
@@ -0,0 +1,30 @@
+package com.baeldung.randomgenerators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGeneratorFactory;
+
+public class SplittableGeneratorMultiThread {
+
+    public static List generateNumbersInMultipleThreads() {
+        List numbers = Collections.synchronizedList(new ArrayList<>());
+        ExecutorService executorService = Executors.newCachedThreadPool();
+
+        RandomGenerator.SplittableGenerator sourceGenerator = RandomGeneratorFactory
+          .of("L128X256MixRandom")
+          .create();
+
+        sourceGenerator.splits(20).forEach((splitGenerator) -> {
+            executorService.submit(() -> {
+                numbers.add(splitGenerator.nextInt(10));
+            });
+        });
+
+        return numbers;
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/module-info.java b/core-java-modules/core-java-17/src/main/java/module-info.java
new file mode 100644
index 0000000000..319678832e
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/module-info.java
@@ -0,0 +1,7 @@
+module core.java {
+    requires jdk.incubator.vector;
+    requires jdk.incubator.foreign;
+    requires jmh.core;
+    requires jdk.unsupported;
+    exports com.baeldung.randomgenerators.jmh_generated;
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/main/resources/compile_c.sh b/core-java-modules/core-java-17/src/main/resources/compile_c.sh
new file mode 100755
index 0000000000..d2e0629cc5
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/resources/compile_c.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
+
+gcc -c -fPIC $SCRIPTPATH/print_name.c
+gcc -shared -rdynamic -o print_name.so print_name.o
+
+mv print_name.so $SCRIPTPATH/
+mv print_name.o $SCRIPTPATH/
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/main/resources/print_name.c b/core-java-modules/core-java-17/src/main/resources/print_name.c
new file mode 100644
index 0000000000..7bda12e352
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/resources/print_name.c
@@ -0,0 +1,8 @@
+#include
+#include
+
+char* printName(char *name) {
+    char* newString = (char*)malloc((15 + sizeof(name))*sizeof(char));
+    sprintf(newString, "Your name is %s", name);
+    return newString;
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP356UnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP356UnitTest.java
new file mode 100644
index 0000000000..b4f61a6f24
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP356UnitTest.java
@@ -0,0 +1,19 @@
+package com.baeldung.features;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JEP356UnitTest {
+
+    @Test
+    void getPseudoInts_whenUsingAlgorithmXoroshiro128PlusPlus_shouldReturnStreamOfRandomInteger() {
+        var algorithm = "Xoshiro256PlusPlus";
+        var streamSize = 100;
+
+        JEP356 jep356 = new JEP356();
+
+        jep356.getPseudoInts(algorithm, streamSize)
+            .forEach(value -> assertThat(value).isLessThanOrEqualTo(99));
+    }
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP406UnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP406UnitTest.java
new file mode 100644
index 0000000000..87e6f3bec6
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP406UnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.features;
+
+import com.baeldung.features.JEP406.Human;
+import com.baeldung.features.JEP409.Square;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class JEP406UnitTest {
+
+    @Test
+    void checkObject_shouldMatchWithHuman() {
+        var jep406 = new JEP406();
+
+        var human = new Human("John", 31, "Developer");
+
+        var checkResult = jep406.checkObject(human);
+
+        assertEquals("Name: John, age: 31 and profession: Developer", checkResult);
+    }
+
+    @Test
+    void checkShape_shouldMatchWithShape() {
+        var jep406 = new JEP406();
+
+        var square = new Square();
+
+        var checkResult = jep406.checkShape(square);
+
+        assertEquals("Just a normal shape", checkResult);
+    }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP409UnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP409UnitTest.java
new file mode 100644
index 0000000000..41380ec2bb
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP409UnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.features;
+
+import com.baeldung.features.JEP409.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+class JEP409UnitTest {
+
+    static class WeirdTriangle extends Triangle {
+        @Override public int getNumberOfSides() {
+            return 40;
+        }
+    }
+
+    @Test
+    void testSealedClass_shouldInvokeRightClass() {
+
+        Shape shape = spy(new WeirdTriangle());
+
+        int numberOfSides = getNumberOfSides(shape);
+
+        assertEquals(40, numberOfSides);
+        verify(shape).getNumberOfSides();
+    }
+
+    int getNumberOfSides(Shape shape) {
+        return switch (shape) {
+            case WeirdTriangle t -> t.getNumberOfSides();
+            case Circle c -> c.getNumberOfSides();
+            case Triangle t -> t.getNumberOfSides();
+            case Rectangle r -> r.getNumberOfSides();
+            case Square s -> s.getNumberOfSides();
+        };
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP412UnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP412UnitTest.java
new file mode 100644
index 0000000000..66e7d952c7
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP412UnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.features;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class JEP412UnitTest {
+
+    @Test
+    void getPrintNameFormat_whenPassingAName_shouldReceiveItFormatted() {
+        var jep412 = new JEP412();
+
+        var formattedName = jep412.getPrintNameFormat("John");
+
+        assertEquals("Your name is John", formattedName);
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP414UnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP414UnitTest.java
new file mode 100644
index 0000000000..459344d907
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/features/JEP414UnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.features;
+
+import org.junit.jupiter.api.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class JEP414UnitTest {
+
+    @Test
+    void vectorComputation_shouldMultiplyVectors() {
+        var jep414 = new JEP414();
+
+        float[] a = initArray(100);
+        float[] b = initArray(100);
+        float[] c = new float[100];
+        float[] d = new float[100];
+
+        jep414.newVectorComputation(a, b, c);
+        jep414.commonVectorComputation(a, b, d);
+
+        for (int i = 0; i < a.length; i++) {
+            assertEquals(c[i], d[i]);
+        }
+    }
+
+    private float[] initArray(int size) {
+        final var jep356 = new JEP356();
+        final var values = new float[size];
+        final var pseudoInts = jep356.getPseudoInts("Xoshiro256PlusPlus", size).mapToObj(Float::valueOf).collect(toList());
+
+        for (int i = 0; i < pseudoInts.size(); i++) {
+            values[i] = pseudoInts.get(i);
+        }
+
+        return values;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/ByteHexadecimalConversionUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/ByteHexadecimalConversionUnitTest.java
new file mode 100644
index 0000000000..29b6eb1bee
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/ByteHexadecimalConversionUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.hexformat;
+
+import java.util.HexFormat;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ByteHexadecimalConversionUnitTest {
+
+    private HexFormat hexFormat = HexFormat.of();
+
+    @Test
+    void givenInitialisedHexFormat_whenHexStringIsPassed_thenByteArrayRepresentationIsReturned() {
+        byte[] hexBytes = hexFormat.parseHex("ABCDEF0123456789");
+        assertArrayEquals(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119 }, hexBytes);
+    }
+
+    @Test
+    void givenInitialisedHexFormat_whenByteArrayIsPassed_thenHexStringRepresentationIsReturned() {
+        String bytesAsString = hexFormat.formatHex(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119});
+        assertEquals("abcdef0123456789", bytesAsString);
+    }
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/PrimitiveTypeHexadecimalConversionUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/PrimitiveTypeHexadecimalConversionUnitTest.java
new file mode 100644
index 0000000000..6f26a8351c
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/PrimitiveTypeHexadecimalConversionUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.hexformat;
+
+import java.util.HexFormat;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PrimitiveTypeHexadecimalConversionUnitTest {
+
+    private HexFormat hexFormat = HexFormat.of();
+
+    @Test
+    void givenInitialisedHexFormat_whenPrimitiveByteIsPassed_thenHexStringRepresentationIsReturned() {
+        String fromByte = hexFormat.toHexDigits((byte)64);
+        assertEquals("40", fromByte);
+    }
+
+    @Test
+    void givenInitialisedHexFormat_whenPrimitiveLongIsPassed_thenHexStringRepresentationIsReturned() {
+        String fromLong = hexFormat.toHexDigits(1234_5678_9012_3456L);
+        assertEquals("000462d53c8abac0", fromLong);
+    }
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/StringFormattingUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/StringFormattingUnitTest.java
new file mode 100644
index 0000000000..28189d0e8c
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/StringFormattingUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.hexformat;
+
+import java.util.HexFormat;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class StringFormattingUnitTest {
+
+    private HexFormat hexFormat = HexFormat.of().withPrefix("[").withSuffix("]").withDelimiter(", ");
+
+    @Test
+    public void givenInitialisedHexFormatWithFormattedStringOptions_whenByteArrayIsPassed_thenHexStringRepresentationFormattedCorrectlyIsReturned() {
+        assertEquals("[48], [0c], [11]", hexFormat.formatHex(new byte[] {72, 12, 17}));
+    }
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/UppercaseLowercaseOutputUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/UppercaseLowercaseOutputUnitTest.java
new file mode 100644
index 0000000000..c2a33fb4b5
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/hexformat/UppercaseLowercaseOutputUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.hexformat;
+
+import java.util.HexFormat;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class UppercaseLowercaseOutputUnitTest {
+
+    @Test
+    public void givenInitialisedHexFormat_whenByteArrayIsPassed_thenLowerCaseHexStringRepresentationIsReturned() {
+        HexFormat hexFormat = HexFormat.of();
+        String bytesAsString = hexFormat.formatHex(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119});
+        assertTrue(isLowerCase(bytesAsString));
+    }
+
+    @Test
+    public void givenInitialisedHexFormatWithUpperCaseOption_whenByteArrayIsPassed_thenLowerCaseHexStringRepresentationIsReturned() {
+        HexFormat hexFormat = HexFormat.of().withUpperCase();
+        String bytesAsString = hexFormat.formatHex(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119});
+        assertTrue(isUpperCase(bytesAsString));
+    }
+
+    private boolean isLowerCase(String str) {
+        char[] charArray = str.toCharArray();
+        for (int i=0; i < charArray.length; i++) {
+            if (Character.isUpperCase(charArray[i]))
+                return false;
+        }
+        return true;
+    }
+
+    private boolean isUpperCase(String str) {
+        char[] charArray = str.toCharArray();
+        for (int i=0; i < charArray.length; i++) {
+            if (Character.isLowerCase(charArray[i]))
+                return false;
+        }
+        return true;
+    }
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/instantsource/InstantExampleUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/instantsource/InstantExampleUnitTest.java
new file mode 100644
index 0000000000..68bc084ba6
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/instantsource/InstantExampleUnitTest.java
@@ -0,0 +1,87 @@
+package com.baeldung.instantsource;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.InstantSource;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class InstantExampleUnitTest {
+
+    @Test
+    void getCurrentInstantFromWrapper_shouldReturnCurrentInstantBasedOnSystemClock() {
+        //given
+        InstantExample tested = new InstantExample(InstantWrapper.of(), null);
+        Instant currentInstant = Clock.systemDefaultZone().instant();
+        //when
+        Instant returnedInstant = tested.getCurrentInstantFromWrapper();
+
+        //then
+        assertTrue(returnedInstant.isAfter(currentInstant));
+    }
+
+    @Test
+    void getCurrentInstantFromWrapper_shouldReturnFixedInstant() {
+        //given
+        LocalDateTime now = LocalDateTime.now();
+        InstantExample tested = new InstantExample(InstantWrapper.of(now), null);
+        Instant currentInstant = now.toInstant(ZoneOffset.UTC);
+        //when
+        Instant returnedInstant = tested.getCurrentInstantFromWrapper();
+
+        //then
+        assertEquals(currentInstant, returnedInstant);
+    }
+
+    @Test
+    void getCurrentInstantFromInstantSource_shouldReturnCurrentInstantBasedOnSystemClock() {
+        //given
+        InstantSource instantSource = InstantSource.system();
+        InstantExample tested = new InstantExample(null, instantSource);
+        Instant currentInstant = instantSource.instant();
+
+        //when
+        Instant returnedInstant = tested.getCurrentInstantFromInstantSource();
+
+        //then
+        assertTrue(returnedInstant.isAfter(currentInstant));
+    }
+
+    @Test
+    void getCurrentInstantFromInstantSource_shouldReturnFixedInstant() {
+        //given
+        LocalDateTime now = LocalDateTime.now();
+        InstantSource instantSource = InstantSource.fixed(now.toInstant(ZoneOffset.UTC));
+        InstantExample tested = new InstantExample(null, instantSource);
+        Instant currentInstant = instantSource.instant();
+
+        LocalDateTime fixed = LocalDateTime.of(2022, 01, 01, 00, 00);
+        Instant i = InstantSource.fixed(fixed.toInstant(ZoneOffset.UTC)).instant();
+        System.out.println(i);
+
+        //when
+        Instant returnedInstant = tested.getCurrentInstantFromInstantSource();
+
+        //then
+        assertEquals(currentInstant, returnedInstant);
+    }
+
+    @Test
+    void getCurrentInstantFromInstantSource_shouldMatchGivenTimezone() {
+        //given
+        LocalDateTime now = LocalDateTime.now();
+        InstantSource instantSource = InstantSource.fixed(now.toInstant(ZoneOffset.of("-4")));
+        InstantExample tested = new InstantExample(null, instantSource);
+
+        //when
+        Instant returnedInstant = tested.getCurrentInstantFromInstantSource();
+
+        //then
+        assertEquals(now.atOffset(ZoneOffset.of("-4")).toInstant(), returnedInstant);
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java
new file mode 100644
index 0000000000..b009b4eeb0
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java
@@ -0,0 +1,21 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class GeneratorFactoryUnitTest {
+
+    @Test
+    void givenDefaultGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+        int number = GeneratorFactory.getRandomInt(GeneratorFactory.getDefaultGenerator(), 10);
+        assertThat(number).isNotNegative().isLessThan(10);
+    }
+
+    @Test
+    void givenJumpableGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+        int number = GeneratorFactory.getRandomInt(GeneratorFactory.getJumpableGenerator(), 10);
+        assertThat(number).isNotNegative().isLessThan(10);
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java
new file mode 100644
index 0000000000..0732c3f54e
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java
@@ -0,0 +1,25 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.random.RandomGenerator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class GeneratorSelectionUnitTest {
+
+    @Test
+    void givenDefaultGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+        RandomGenerator generator = RandomGenerator.getDefault();
+        int number = generator.nextInt(10);
+        assertThat(number).isNotNegative().isLessThan(10);
+    }
+
+    @Test
+    void givenSpecificGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+        RandomGenerator generator = RandomGenerator.of("L128X256MixRandom");
+        int number = generator.nextInt(10);
+        assertThat(number).isNotNegative().isLessThan(10);
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java
new file mode 100644
index 0000000000..4a18369686
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class OldRandomUnitTest {
+
+    @Test
+    void givenOldRandomApi_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+        int number = OldRandom.getRandomInt(10);
+        assertThat(number).isNotNegative().isLessThan(10);
+    }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java
new file mode 100644
index 0000000000..ba4cd8eb2b
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SplittableGeneratorMultiThreadUnitTest {
+
+    @Test
+    void givenSplittableGenerator_whenUsingMultipleThreads_thenListOfIntsIsGenerated() {
+        List numbers = SplittableGeneratorMultiThread.generateNumbersInMultipleThreads();
+        assertThat(numbers).hasSize(20).allMatch(number -> number >= 0 && number <= 10);
+    }
+
+}
diff --git a/core-java-modules/core-java-8-2/pom.xml b/core-java-modules/core-java-8-2/pom.xml
index af26289db8..7db1e1ed4e 100644
--- a/core-java-modules/core-java-8-2/pom.xml
+++ b/core-java-modules/core-java-8-2/pom.xml
@@ -20,17 +20,10 @@
             icu4j
             ${icu.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
         64.2
-        3.12.2
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/game/RockPaperScissorsGame.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/game/RockPaperScissorsGame.java
new file mode 100644
index 0000000000..fc9299f12d
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/game/RockPaperScissorsGame.java
@@ -0,0 +1,66 @@
+package com.baeldung.game;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.Scanner;
+
+class RockPaperScissorsGame {
+
+    private static Map movesMap = new HashMap() {{
+        put(0, "rock");
+        put(1, "paper");
+        put(2, "scissors");
+    }};
+
+    public static void main(String[] args) {
+        Scanner scanner = new Scanner(System.in);
+        int wins = 0;
+        int losses = 0;
+
+        System.out.println("Welcome to Rock-Paper-Scissors! Please enter \"rock\", \"paper\", \"scissors\", or \"quit\" to exit.");
+
+        while (true) {
+            System.out.println("-------------------------");
+            System.out.print("Enter your move: ");
+            String playerMove = scanner.nextLine();
+
+            if (playerMove.equals("quit")) {
+                System.out.println("You won " + wins + " times and lost " + losses + " times.");
+                System.out.println("Thanks for playing! See you again.");
+                break;
+            }
+
+            if (!movesMap.containsValue(playerMove)) {
+                System.out.println("Your move isn't valid!");
+                continue;
+            }
+
+            String computerMove = getComputerMove();
+
+            if (playerMove.equals(computerMove)) {
+                System.out.println("It's a tie!");
+            } else if (isPlayerWin(playerMove, computerMove)) {
+                System.out.println("You won!");
+                wins++;
+            } else {
+                System.out.println("You lost!");
+                losses++;
+            }
+        }
+    }
+
+    private static boolean isPlayerWin(String playerMove, String computerMove) {
+        return playerMove.equals("rock") && computerMove.equals("scissors")
+                || (playerMove.equals("scissors") && computerMove.equals("paper"))
+                || (playerMove.equals("paper") && computerMove.equals("rock"));
+    }
+
+    private static String getComputerMove() {
+        Random random = new Random();
+        int randomNumber = random.nextInt(3);
+        String computerMove = movesMap.get(randomNumber);
+        System.out.println("Computer move: " + computerMove);
+        return computerMove;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/uuid/UuidHelper.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/uuid/UuidHelper.java
new file mode 100644
index 0000000000..5807262094
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/uuid/UuidHelper.java
@@ -0,0 +1,33 @@
+package com.baeldung.uuid;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+public class UuidHelper {
+
+    public static byte[] convertUUIDToBytes(UUID uuid) {
+        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
+        bb.putLong(uuid.getMostSignificantBits());
+        bb.putLong(uuid.getLeastSignificantBits());
+        return bb.array();
+    }
+
+    public static UUID convertBytesToUUID(byte[] bytes) {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+        long high = byteBuffer.getLong();
+        long low = byteBuffer.getLong();
+        return new UUID(high, low);
+    }
+
+    public static void main(String[] args) {
+        UUID uuid = UUID.randomUUID();
+        System.out.println("Original UUID: " + uuid);
+
+        byte[] bytes = convertUUIDToBytes(uuid);
+        System.out.println("Converted byte array: " + Arrays.toString(bytes));
+
+        UUID uuidNew = convertBytesToUUID(bytes);
+        System.out.println("Converted UUID: " + uuidNew);
+    }
+}
diff --git a/core-java-modules/core-java-8-datetime-2/pom.xml b/core-java-modules/core-java-8-datetime-2/pom.xml
index e662ba400c..9e54b0ee12 100644
--- a/core-java-modules/core-java-8-datetime-2/pom.xml
+++ b/core-java-modules/core-java-8-datetime-2/pom.xml
@@ -25,12 +25,6 @@
             joda-time
             ${joda-time.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             log4j
             log4j
@@ -63,8 +57,6 @@
         1.8
         1.8
         2.10
-        
-        3.6.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-datetime/README.md b/core-java-modules/core-java-8-datetime/README.md
index c35683a589..03d2a9609d 100644
--- a/core-java-modules/core-java-8-datetime/README.md
+++ b/core-java-modules/core-java-8-datetime/README.md
@@ -5,7 +5,7 @@ This module contains articles about the Date and Time API introduced with Java 8
 ### Relevant Articles: 
 - [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
 - [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
-- [Get the Current Date, Time and Timestamp in Java 8](http://www.baeldung.com/current-date-time-and-timestamp-in-java-8)
+- [Get the Current Date and Time in Java](https://www.baeldung.com/current-date-time-and-timestamp-in-java-8)
 - [TemporalAdjuster in Java](http://www.baeldung.com/java-temporal-adjuster)
 - [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset)
 - [Differences Between ZonedDateTime and OffsetDateTime](https://www.baeldung.com/java-zoneddatetime-offsetdatetime)
diff --git a/core-java-modules/core-java-8-datetime/pom.xml b/core-java-modules/core-java-8-datetime/pom.xml
index f58557df7f..01ec6c0b76 100644
--- a/core-java-modules/core-java-8-datetime/pom.xml
+++ b/core-java-modules/core-java-8-datetime/pom.xml
@@ -25,12 +25,6 @@
             joda-time
             ${joda-time.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             log4j
             log4j
@@ -64,8 +58,6 @@
         1.8
         1.8
         2.10
-        
-        3.6.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/pom.xml b/core-java-modules/core-java-8/pom.xml
index 987ba2e568..89925bdbbb 100644
--- a/core-java-modules/core-java-8/pom.xml
+++ b/core-java-modules/core-java-8/pom.xml
@@ -31,13 +31,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -50,11 +43,4 @@
         
     
 
-    
-        
-        4.1
-        
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-improvements/pom.xml b/core-java-modules/core-java-9-improvements/pom.xml
index 6abdd7dab8..56d4ccff9f 100644
--- a/core-java-modules/core-java-9-improvements/pom.xml
+++ b/core-java-modules/core-java-9-improvements/pom.xml
@@ -21,12 +21,6 @@
             ${awaitility.version}
             test
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.google.guava
             guava
@@ -68,12 +62,9 @@
     
 
     
-        
-        3.10.0
         1.7.0
         1.9
         1.9
-        25.1-jre
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java b/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
index b909636b56..ed2dcaf695 100644
--- a/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
+++ b/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
@@ -2,12 +2,21 @@ package com.baeldung.java9.modules;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.Matchers.*;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.collection.IsEmptyCollection.empty;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.*;
+
+import java.lang.module.ModuleDescriptor.Builder;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
 import java.sql.Date;
 import java.sql.Driver;
 import java.util.HashMap;
@@ -17,6 +26,7 @@ import java.util.stream.Collectors;
 import org.junit.Before;
 import org.junit.Test;
 
+
 public class ModuleAPIUnitTest {
 
     public static final String JAVA_BASE_MODULE_NAME = "java.base";
@@ -27,14 +37,9 @@ public class ModuleAPIUnitTest {
 
     @Before
     public void setUp() {
-        Class hashMapClass = HashMap.class;
-        javaBaseModule = hashMapClass.getModule();
-
-        Class dateClass = Date.class;
-        javaSqlModule = dateClass.getModule();
-
-        Class personClass = Person.class;
-        module = personClass.getModule();
+        javaBaseModule = HashMap.class.getModule();
+        javaSqlModule = Date.class.getModule();
+        module = Person.class.getModule();
     }
 
     @Test
@@ -118,7 +123,7 @@ public class ModuleAPIUnitTest {
                 .map(Provides::service)
                 .collect(Collectors.toSet());
 
-        assertThat(javaBaseProvidesService, contains("java.nio.file.spi.FileSystemProvider"));
+        assertThat(javaBaseProvidesService, hasItem("java.nio.file.spi.FileSystemProvider"));
         assertThat(javaSqlProvides, empty());
     }
 
@@ -130,15 +135,14 @@ public class ModuleAPIUnitTest {
           .map(Exports::source)
           .collect(Collectors.toSet());
 
-        assertThat(javaSqlExportsSource, hasItems("java.sql",  "javax.sql"));
+        assertThat(javaSqlExportsSource, hasItems("java.sql", "javax.sql"));
     }
 
     @Test
     public void givenModules_whenAccessingModuleDescriptorUses_thenUsesAreReturned() {
-        Set javaBaseUses = javaBaseModule.getDescriptor().uses();
         Set javaSqlUses = javaSqlModule.getDescriptor().uses();
 
-        assertThat(javaSqlUses, contains("java.sql.Driver"));
+        assertThat(javaSqlUses, hasItem("java.sql.Driver"));
     }
 
     @Test
diff --git a/core-java-modules/core-java-9-new-features/pom.xml b/core-java-modules/core-java-9-new-features/pom.xml
index 7dca8d5f88..ce90a0f04a 100644
--- a/core-java-modules/core-java-9-new-features/pom.xml
+++ b/core-java-modules/core-java-9-new-features/pom.xml
@@ -20,12 +20,6 @@
             rxjava
             ${rxjava.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.junit.platform
             junit-platform-runner
@@ -156,8 +150,6 @@
 
     
         3.0.0
-        
-        3.10.0
         4.0.2
         1.9
         1.9
diff --git a/core-java-modules/core-java-9-streams/pom.xml b/core-java-modules/core-java-9-streams/pom.xml
index aeaf2c7f57..d3f81780d1 100644
--- a/core-java-modules/core-java-9-streams/pom.xml
+++ b/core-java-modules/core-java-9-streams/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
diff --git a/core-java-modules/core-java-9/pom.xml b/core-java-modules/core-java-9/pom.xml
index 1bd650f7d2..272af327cb 100644
--- a/core-java-modules/core-java-9/pom.xml
+++ b/core-java-modules/core-java-9/pom.xml
@@ -21,12 +21,6 @@
             ${awaitility.version}
             test
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.google.guava
             guava
@@ -78,14 +72,9 @@
     
 
     
-        
-        3.10.0
         1.7.0
         1.9
         1.9
-        25.1-jre
-        4.1
-        3.2.2
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-annotations/pom.xml b/core-java-modules/core-java-annotations/pom.xml
index a87baa6204..a1f84ab563 100644
--- a/core-java-modules/core-java-annotations/pom.xml
+++ b/core-java-modules/core-java-annotations/pom.xml
@@ -1,7 +1,7 @@
 
 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4.0.0
     core-java-annotations
     0.1.0-SNAPSHOT
@@ -14,19 +14,6 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-    
-
-    
-        3.10.0
-    
-
     
         core-java-annotations
         
@@ -37,4 +24,4 @@
         
     
 
-
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-convert/pom.xml b/core-java-modules/core-java-arrays-convert/pom.xml
index 6e001e12b0..c90b60e09a 100644
--- a/core-java-modules/core-java-arrays-convert/pom.xml
+++ b/core-java-modules/core-java-arrays-convert/pom.xml
@@ -14,11 +14,6 @@
     
 
     
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.apache.commons
             commons-lang3
@@ -26,8 +21,4 @@
         
     
 
-    
-        28.2-jre
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-guides/pom.xml b/core-java-modules/core-java-arrays-guides/pom.xml
index 3dba2dc05f..d22f6b4d7d 100644
--- a/core-java-modules/core-java-arrays-guides/pom.xml
+++ b/core-java-modules/core-java-arrays-guides/pom.xml
@@ -24,12 +24,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-            org.assertj
-            assertj-core
-            3.19.0
-            test
-        
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-operations-advanced/pom.xml b/core-java-modules/core-java-arrays-operations-advanced/pom.xml
index 065f1930e2..cbcd6ae440 100644
--- a/core-java-modules/core-java-arrays-operations-advanced/pom.xml
+++ b/core-java-modules/core-java-arrays-operations-advanced/pom.xml
@@ -19,32 +19,18 @@
             commons-lang3
             ${commons-lang3.version}
         
-
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-
         
             org.openjdk.jmh
             jmh-core
-            ${jmh.version}
+            ${jmh-core.version}
         
-
         
             org.openjdk.jmh
             jmh-generator-annprocess
-            ${jmh.version}
+            ${jmh-generator.version}
         
     
 
-    
-        3.10.0
-        1.33
-    
-
     
         
             
diff --git a/core-java-modules/core-java-arrays-operations-basic/pom.xml b/core-java-modules/core-java-arrays-operations-basic/pom.xml
index 382cee102d..6517b2efb9 100644
--- a/core-java-modules/core-java-arrays-operations-basic/pom.xml
+++ b/core-java-modules/core-java-arrays-operations-basic/pom.xml
@@ -30,12 +30,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -67,7 +61,6 @@
 
     
         3.2.0
-        3.10.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-sorting/pom.xml b/core-java-modules/core-java-arrays-sorting/pom.xml
index e9946d46ed..82e3f659fc 100644
--- a/core-java-modules/core-java-arrays-sorting/pom.xml
+++ b/core-java-modules/core-java-arrays-sorting/pom.xml
@@ -20,11 +20,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
         
             org.openjdk.jmh
@@ -36,13 +31,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -74,8 +62,6 @@
 
     
         3.2.0
-        28.2-jre
-        3.10.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-char/pom.xml b/core-java-modules/core-java-char/pom.xml
index 009197a1d0..7dc0923fb5 100644
--- a/core-java-modules/core-java-char/pom.xml
+++ b/core-java-modules/core-java-char/pom.xml
@@ -15,12 +15,6 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.openjdk.jmh
             jmh-core
@@ -33,8 +27,4 @@
         
     
 
-    
-        3.11.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-2/pom.xml b/core-java-modules/core-java-collections-2/pom.xml
index 0f1f1ee2fe..e78f7b5dda 100644
--- a/core-java-modules/core-java-collections-2/pom.xml
+++ b/core-java-modules/core-java-collections-2/pom.xml
@@ -34,12 +34,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.junit.platform
             junit-platform-runner
@@ -50,8 +44,6 @@
 
     
         7.1.0
-        4.1
-        3.11.1
         1.3
     
 
diff --git a/core-java-modules/core-java-collections-3/README.md b/core-java-modules/core-java-collections-3/README.md
index 6bc9139856..4249d8ad30 100644
--- a/core-java-modules/core-java-collections-3/README.md
+++ b/core-java-modules/core-java-collections-3/README.md
@@ -11,7 +11,7 @@
 - [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
 - [Fail-Safe Iterator vs Fail-Fast Iterator](https://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)
 - [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack)
-- [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list)
 - [A Guide to BitSet in Java](https://www.baeldung.com/java-bitset)
 - [Get the First Key and Value From a HashMap](https://www.baeldung.com/java-hashmap-get-first-entry)
 - [Performance of removeAll() in a HashSet](https://www.baeldung.com/java-hashset-removeall-performance)
+- More articles: [[<-- prev]](/core-java-modules/core-java-collections-2) [[next -->]](/core-java-modules/core-java-collections-4)
diff --git a/core-java-modules/core-java-collections-3/pom.xml b/core-java-modules/core-java-collections-3/pom.xml
index 4ca4bda1ee..6ef8e3c81a 100644
--- a/core-java-modules/core-java-collections-3/pom.xml
+++ b/core-java-modules/core-java-collections-3/pom.xml
@@ -25,12 +25,6 @@
             jmh-core
             ${jmh-core.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.apache.commons
             commons-lang3
@@ -39,7 +33,6 @@
     
 
     
-        3.11.1
         0.10
     
 
diff --git a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/iterators/Iterators.java b/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/iterators/Iterators.java
index 23e6bbda77..4daf7dd9d1 100644
--- a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/iterators/Iterators.java
+++ b/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/iterators/Iterators.java
@@ -1,17 +1,16 @@
 package com.baeldung.collections.iterators;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
 
-/**
- * Source code https://github.com/eugenp/tutorials
- *
- * @author Santosh Thakur
- */
-
 public class Iterators {
 
+    private static final Logger LOG = LoggerFactory.getLogger(Iterators.class);
+
     public static int failFast1() {
         ArrayList numbers = new ArrayList<>();
 
@@ -44,7 +43,7 @@ public class Iterators {
             }
         }
 
-        System.out.println("using iterator's remove method = " + numbers);
+        LOG.debug("using iterator's remove method = {}", numbers);
 
         iterator = numbers.iterator();
         while (iterator.hasNext()) {
diff --git a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/bitset/BitSetUnitTest.java b/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/bitset/BitSetUnitTest.java
index d9340f45c1..7141dbf79f 100644
--- a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/bitset/BitSetUnitTest.java
+++ b/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/bitset/BitSetUnitTest.java
@@ -3,6 +3,8 @@ package com.baeldung.collections.bitset;
 import org.junit.Test;
 import org.openjdk.jol.info.ClassLayout;
 import org.openjdk.jol.info.GraphLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.BitSet;
 
@@ -10,18 +12,20 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class BitSetUnitTest {
 
+    private static final Logger LOG = LoggerFactory.getLogger(BitSetUnitTest.class);
+
     @Test
     public void givenBoolArray_whenMemoryLayout_thenConsumeMoreThanOneBit() {
         boolean[] bits = new boolean[1024 * 1024];
 
-        System.out.println(ClassLayout.parseInstance(bits).toPrintable());
+        LOG.debug(ClassLayout.parseInstance(bits).toPrintable());
     }
 
     @Test
     public void givenBitSet_whenMemoryLayout_thenConsumeOneBitPerFlag() {
         BitSet bitSet = new BitSet(1024 * 1024);
 
-        System.out.println(GraphLayout.parseInstance(bitSet).toPrintable());
+        LOG.debug(GraphLayout.parseInstance(bitSet).toPrintable());
     }
 
     @Test
@@ -157,7 +161,7 @@ public class BitSetUnitTest {
         BitSet bitSet = new BitSet();
         bitSet.set(15, 25);
 
-        bitSet.stream().forEach(System.out::println);
+        bitSet.stream().forEach(bit -> LOG.debug(String.valueOf(bit)));
         assertThat(bitSet.stream().count()).isEqualTo(10);
     }
 
diff --git a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java b/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java
index 6a2feff551..14eafe8924 100644
--- a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java
+++ b/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.stack;
+package com.baeldung.collections.stack;
 
 import org.junit.Test;
 
diff --git a/guest/spring-boot-app/src/main/resources/logback.xml b/core-java-modules/core-java-collections-3/src/test/resources/logback.xml
similarity index 100%
rename from guest/spring-boot-app/src/main/resources/logback.xml
rename to core-java-modules/core-java-collections-3/src/test/resources/logback.xml
diff --git a/core-java-modules/core-java-collections-4/pom.xml b/core-java-modules/core-java-collections-4/pom.xml
index d86b04644c..2193b5118a 100644
--- a/core-java-modules/core-java-collections-4/pom.xml
+++ b/core-java-modules/core-java-collections-4/pom.xml
@@ -14,17 +14,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-    
-
-    
-        3.19.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/DynamicTypeValue.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/DynamicTypeValue.java
new file mode 100644
index 0000000000..4c9ed89f63
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/DynamicTypeValue.java
@@ -0,0 +1,5 @@
+package com.baeldung.collections.mulipletypesinmap;
+
+public interface DynamicTypeValue {
+    String valueDescription();
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/InstantTypeValue.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/InstantTypeValue.java
new file mode 100644
index 0000000000..448e66d872
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/InstantTypeValue.java
@@ -0,0 +1,24 @@
+package com.baeldung.collections.mulipletypesinmap;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+public class InstantTypeValue implements DynamicTypeValue {
+    private static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+        .withZone(ZoneId.systemDefault());
+    private Instant value;
+
+    public InstantTypeValue(Instant value) {
+        this.value = value;
+    }
+
+    @Override
+    public String valueDescription() {
+        if (value == null) {
+            return "The value is null.";
+        }
+        return String.format("The value is an instant: %s", FORMATTER.format(value));
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntArrayTypeValue.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntArrayTypeValue.java
new file mode 100644
index 0000000000..290982183f
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntArrayTypeValue.java
@@ -0,0 +1,20 @@
+package com.baeldung.collections.mulipletypesinmap;
+
+import java.util.Arrays;
+
+public class IntArrayTypeValue implements DynamicTypeValue {
+    private int[] value;
+
+    public IntArrayTypeValue(int[] value) {
+        this.value = value;
+    }
+
+    @Override
+    public String valueDescription() {
+        if (value == null) {
+            return "The value is null.";
+        }
+        return String.format("The value is an array of %d integers: %s", value.length, Arrays.toString(value));
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntegerTypeValue.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntegerTypeValue.java
new file mode 100644
index 0000000000..463b06f768
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/mulipletypesinmap/IntegerTypeValue.java
@@ -0,0 +1,17 @@
+package com.baeldung.collections.mulipletypesinmap;
+
+public class IntegerTypeValue implements DynamicTypeValue {
+    private Integer value;
+
+    public IntegerTypeValue(Integer value) {
+        this.value = value;
+    }
+
+    @Override
+    public String valueDescription() {
+        if(value == null){
+            return "The value is null.";
+        }
+        return String.format("The value is a %s integer: %d", value > 0 ? "positive" : "negative", value);
+    }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java
new file mode 100644
index 0000000000..3dc644f1af
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java
@@ -0,0 +1,56 @@
+package com.baeldung.maps.initialize;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+public class EmptyMapInitializer {
+
+  public static Map articleMap;
+  static {
+    articleMap = new HashMap<>();
+  }
+
+  public static Map createEmptyMap() {
+    return Collections.emptyMap();
+  }
+
+  public void createMapUsingConstructors() {
+    Map hashMap = new HashMap();
+    Map linkedHashMap = new LinkedHashMap();
+    Map treeMap = new TreeMap();
+  }
+
+  public Map createEmptyMapUsingMapsObject() {
+    Map emptyMap = Maps.newHashMap();
+    return emptyMap;
+  }
+
+  public Map createGenericEmptyMapUsingMapsObject() {
+    Map genericEmptyMap = Maps.newHashMap();
+    return genericEmptyMap;
+  }
+
+  public static Map createMapUsingGuava() {
+    Map emptyMapUsingGuava =
+        Maps.newHashMap(ImmutableMap.of());
+    return emptyMapUsingGuava;
+  }
+
+  public SortedMap createEmptySortedMap() {
+    SortedMap sortedMap = Collections.emptySortedMap();
+    return sortedMap;
+  }
+
+  public NavigableMap createEmptyNavigableMap() {
+    NavigableMap navigableMap = Collections.emptyNavigableMap();
+    return navigableMap;
+  }
+
+}
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java
new file mode 100644
index 0000000000..cc25205ba7
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.maps.initialize;
+
+import java.util.Map;
+import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class EmptyMapInitializerUnitTest {
+
+  @Test(expected=UnsupportedOperationException.class)
+  public void givenEmptyMap_whenAddingEntries_throwsException() {
+    Map map = EmptyMapInitializer.createEmptyMap();
+    map.put("key", "value");
+  }
+
+  @Test
+  public void givenEmptyMap_whenChecked_returnsTrue() {
+    assertTrue(EmptyMapInitializer.articleMap.isEmpty());
+  }
+
+  @Test
+  public void givenEmptyMap_whenCreatedUsingGuava_returnsEmptyOrNot() {
+    Map emptyMapUsingGuava =
+        EmptyMapInitializer.createMapUsingGuava();
+    assertTrue(emptyMapUsingGuava.isEmpty());
+    emptyMapUsingGuava.put("key", "value");
+    assertFalse(emptyMapUsingGuava.isEmpty());
+  }
+
+}
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/multipletypesinmap/MultipleTypesInMapUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/multipletypesinmap/MultipleTypesInMapUnitTest.java
new file mode 100644
index 0000000000..87ea310ab0
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/multipletypesinmap/MultipleTypesInMapUnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.multipletypesinmap;
+
+import com.baeldung.collections.mulipletypesinmap.DynamicTypeValue;
+import com.baeldung.collections.mulipletypesinmap.InstantTypeValue;
+import com.baeldung.collections.mulipletypesinmap.IntArrayTypeValue;
+import com.baeldung.collections.mulipletypesinmap.IntegerTypeValue;
+import org.junit.jupiter.api.Test;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class MultipleTypesInMapUnitTest {
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+        .withZone(ZoneId.systemDefault());
+
+    private static final Integer intValue = 777;
+    private static final int[] intArray = new int[]{2, 3, 5, 7, 11, 13};
+    private static final Instant instant = Instant.now();
+
+    private static final String KEY_INT = "E1 (Integer)";
+    private static final String KEY_INT_ARRAY = "E2 (IntArray)";
+    private static final String KEY_INSTANT = "E3 (Instant)";
+
+    @Test
+    void givenThreeTypes_whenUsingRawMap_thenPrintDescription() {
+        Map rawMap = new HashMap<>();
+        rawMap.put(KEY_INT, intValue);
+        rawMap.put(KEY_INT_ARRAY, intArray);
+        rawMap.put(KEY_INSTANT, instant);
+
+        rawMap.forEach((k, v) -> {
+            if (v instanceof Integer) {
+                Integer theV = (Integer) v;
+                String desc = String.format("The value is a %s integer: %d", theV > 0 ? "positive" : "negative", theV);
+                System.out.println(k + " -> " + desc);
+                assertThat(k).isEqualTo(KEY_INT);
+                assertThat(desc).isEqualTo("The value is a positive integer: 777");
+            } else if (v instanceof int[]) {
+                int[] theV = (int[]) v;
+                String desc = String.format("The value is an array of %d integers: %s", theV.length, Arrays.toString(theV));
+                System.out.println(k + " -> " + desc);
+                assertThat(k).isEqualTo(KEY_INT_ARRAY);
+                assertThat(desc).isEqualTo("The value is an array of 6 integers: [2, 3, 5, 7, 11, 13]");
+            } else if (v instanceof Instant) {
+                Instant theV = (Instant) v;
+                String desc = String.format("The value is an instant: %s", FORMATTER.format(theV));
+                System.out.println(k + " -> " + desc);
+                assertThat(k).isEqualTo(KEY_INSTANT);
+                assertThat(desc).matches("^The value is an instant: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
+            } else {
+                throw new IllegalStateException("Unknown Type found.");
+            }
+        });
+    }
+
+    @Test
+    void givenThreeTypes_whenUsingAnInterface_thenPrintDescription() {
+        Map theMap = new HashMap<>();
+        theMap.put(KEY_INT, new IntegerTypeValue(intValue));
+        theMap.put(KEY_INT_ARRAY, new IntArrayTypeValue(intArray));
+        theMap.put(KEY_INSTANT, new InstantTypeValue(instant));
+
+        theMap.forEach((k, v) -> System.out.println(k + " -> " + v.valueDescription()));
+
+        assertThat(theMap.get(KEY_INT).valueDescription()).isEqualTo("The value is a positive integer: 777");
+        assertThat(theMap.get(KEY_INT_ARRAY).valueDescription()).isEqualTo("The value is an array of 6 integers: [2, 3, 5, 7, 11, 13]");
+        assertThat(theMap.get(KEY_INSTANT).valueDescription()).matches("^The value is an instant: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
+    }
+}
diff --git a/core-java-modules/core-java-collections-array-list/pom.xml b/core-java-modules/core-java-collections-array-list/pom.xml
index c14e59bac0..6b040739e8 100644
--- a/core-java-modules/core-java-collections-array-list/pom.xml
+++ b/core-java-modules/core-java-collections-array-list/pom.xml
@@ -20,17 +20,6 @@
             commons-collections4
             ${commons-collections4.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        4.1
-        3.11.1
-    
-
 
\ 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
index 51e66fc0c2..59ab8c5f27 100644
--- a/core-java-modules/core-java-collections-list-2/pom.xml
+++ b/core-java-modules/core-java-collections-list-2/pom.xml
@@ -20,12 +20,6 @@
             commons-collections4
             ${commons-collections4.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.projectlombok
             lombok
@@ -34,9 +28,4 @@
         
     
 
-    
-        4.1
-        3.11.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-list-3/pom.xml b/core-java-modules/core-java-collections-list-3/pom.xml
index efe79509c1..912204bcc6 100644
--- a/core-java-modules/core-java-collections-list-3/pom.xml
+++ b/core-java-modules/core-java-collections-list-3/pom.xml
@@ -20,18 +20,6 @@
             commons-collections4
             ${commons-collections4.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-            compile
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             net.sf.trove4j
             trove4j
@@ -60,8 +48,6 @@
     
 
     
-        4.1
-        3.11.1
         3.0.2
         8.1.0
         1.2.0
diff --git a/core-java-modules/core-java-collections-list/pom.xml b/core-java-modules/core-java-collections-list/pom.xml
index ae1e1561c6..0cc8828a0d 100644
--- a/core-java-modules/core-java-collections-list/pom.xml
+++ b/core-java-modules/core-java-collections-list/pom.xml
@@ -25,17 +25,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        4.1
-        3.11.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/pom.xml b/core-java-modules/core-java-collections-maps-2/pom.xml
index 772cf30416..36b15c24d5 100644
--- a/core-java-modules/core-java-collections-maps-2/pom.xml
+++ b/core-java-modules/core-java-collections-maps-2/pom.xml
@@ -51,22 +51,14 @@
             ${avaitility.version}
             test
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
         0.6.5
-        4.1
         1.7.0
         8.2.0
         0.7.2
         8.1.0
-        3.11.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java
index b0c32e1487..2d8b17e5e7 100644
--- a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java
@@ -17,22 +17,45 @@ public class MapIteration {
         System.out.println("Iterating Keys of Map Using KeySet");
         mapIteration.iterateKeys(map);
 
+        System.out.println("Iterating Values of Map Using values()");
+        mapIteration.iterateValues(map);
+
         System.out.println("Iterating Map Using Entry Set");
         mapIteration.iterateUsingEntrySet(map);
 
         System.out.println("Iterating Using Iterator and Map Entry");
         mapIteration.iterateUsingIteratorAndEntry(map);
 
+        System.out.println("Iterating Using Iterator and KeySet");
+        mapIteration.iterateUsingIteratorAndKeySet(map);
+
+        System.out.println("Iterating values Using Iterator and values()");
+        mapIteration.iterateUsingIteratorAndValues(map);
+
         System.out.println("Iterating Using KeySet and For Each");
         mapIteration.iterateUsingKeySetAndForeach(map);
 
         System.out.println("Iterating Map Using Lambda Expression");
         mapIteration.iterateUsingLambda(map);
 
+        System.out.println("Iterating Map By Keys Using Lambda Expression");
+        mapIteration.iterateByKeysUsingLambda(map);
+
+        System.out.println("Iterating values Using Lambda Expression");
+        mapIteration.iterateValuesUsingLambda(map);
+
         System.out.println("Iterating Using Stream API");
         mapIteration.iterateUsingStreamAPI(map);
     }
 
+    public void iterateUsingIteratorAndValues(Map map) {
+        Iterator iterator = map.values().iterator();
+        while (iterator.hasNext()) {
+            Integer value = iterator.next();
+            System.out.println("value :" + value);
+        }
+    }
+
     public void iterateUsingEntrySet(Map map) {
         for (Map.Entry entry : map.entrySet()) {
             System.out.println(entry.getKey() + ":" + entry.getValue());
@@ -43,6 +66,14 @@ public class MapIteration {
         map.forEach((k, v) -> System.out.println((k + ":" + v)));
     }
 
+    public void iterateByKeysUsingLambda(Map map) {
+        map.keySet().forEach(k -> System.out.println((k + ":" + map.get(k))));
+    }
+
+    public void iterateValuesUsingLambda(Map map) {
+        map.values().forEach(v -> System.out.println(("value: " + v)));
+    }
+
     public void iterateUsingIteratorAndEntry(Map map) {
         Iterator> iterator = map.entrySet()
             .iterator();
@@ -52,6 +83,14 @@ public class MapIteration {
         }
     }
 
+    public void iterateUsingIteratorAndKeySet(Map map) {
+        Iterator iterator = map.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            System.out.println(key + ":" + map.get(key));
+        }
+    }
+
     public void iterateUsingKeySetAndForeach(Map map) {
         for (String key : map.keySet()) {
             System.out.println(key + ":" + map.get(key));
@@ -68,7 +107,12 @@ public class MapIteration {
         for (String key : map.keySet()) {
             System.out.println(key);
         }
+    }
 
+    public void iterateValues(Map map) {
+        for (Integer value : map.values()) {
+            System.out.println(value);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-3/pom.xml b/core-java-modules/core-java-collections-maps-3/pom.xml
index c534c1d5ca..a5bb6dc338 100644
--- a/core-java-modules/core-java-collections-maps-3/pom.xml
+++ b/core-java-modules/core-java-collections-maps-3/pom.xml
@@ -20,11 +20,6 @@
             jmh-core
             ${jmh-core.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-4/README.md b/core-java-modules/core-java-collections-maps-4/README.md
index 54ab60da7d..795f0df702 100644
--- a/core-java-modules/core-java-collections-maps-4/README.md
+++ b/core-java-modules/core-java-collections-maps-4/README.md
@@ -4,3 +4,5 @@ This module contains articles about Map data structures in Java.
 
 ### Relevant Articles: 
 - [Using a Custom Class as a Key in a Java HashMap](https://www.baeldung.com/java-custom-class-map-key)
+- [Nested HashMaps Examples in Java](https://www.baeldung.com/java-nested-hashmaps)
+- [Java HashMap With Different Value Types](https://www.baeldung.com/java-hashmap-different-value-types)
diff --git a/core-java-modules/core-java-collections-maps-4/pom.xml b/core-java-modules/core-java-collections-maps-4/pom.xml
index 1835e3ceac..be467dd57b 100644
--- a/core-java-modules/core-java-collections-maps-4/pom.xml
+++ b/core-java-modules/core-java-collections-maps-4/pom.xml
@@ -1,7 +1,7 @@
 
 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4.0.0
     core-java-collections-maps-4
     0.1.0-SNAPSHOT
@@ -12,9 +12,17 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../pom.xml
     
 
+    
+        
+            junit
+            junit
+            ${junit.version}
+            test
+        
+    
+
     
         
             
@@ -31,4 +39,10 @@
         
     
 
-
+    
+        UTF-8
+        1.8
+        1.8
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/Main.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/Main.java
new file mode 100644
index 0000000000..1024399a98
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/Main.java
@@ -0,0 +1,25 @@
+package com.baeldung.mapandhashmap;
+
+import com.baeldung.mapandhashmap.printer.HashMapPrinter;
+import com.baeldung.mapandhashmap.printer.MapPrinter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class Main {
+    public static void main(String[] args) {
+        Map map = new HashMap<>();
+        HashMap hashMap = new HashMap<>();
+        TreeMap treeMap = new TreeMap<>();
+
+        HashMapPrinter hashMapPrinter = new HashMapPrinter();
+        hashMapPrinter.printMap(hashMap);
+//        hashMapPrinter.printMap(treeMap); Compile time error
+//        hashMapPrinter.printMap(map); Compile time error
+
+        MapPrinter mapPrinter = new MapPrinter();
+        mapPrinter.printMap(hashMap);
+        mapPrinter.printMap(treeMap);
+        mapPrinter.printMap(map);
+    }
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/HashMapPrinter.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/HashMapPrinter.java
new file mode 100644
index 0000000000..53c78bfc55
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/HashMapPrinter.java
@@ -0,0 +1,13 @@
+package com.baeldung.mapandhashmap.printer;
+
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+public class HashMapPrinter {
+
+    public void printMap(final HashMap map) {
+        for (final Entry entry : map.entrySet()) {
+            System.out.println(entry.getKey() + " " + entry.getValue());
+        }
+    }
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapPrinter.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapPrinter.java
new file mode 100644
index 0000000000..e5c0ab49cd
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapPrinter.java
@@ -0,0 +1,13 @@
+package com.baeldung.mapandhashmap.printer;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class MapPrinter {
+
+    public void printMap(final Map map) {
+        for (final Entry entry : map.entrySet()) {
+            System.out.println(entry.getKey() + " " + entry.getValue());
+        }
+    }
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapReporter.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapReporter.java
new file mode 100644
index 0000000000..fd7347c2d1
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/mapandhashmap/printer/MapReporter.java
@@ -0,0 +1,19 @@
+package com.baeldung.mapandhashmap.printer;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class MapReporter {
+
+    private final Map map;
+
+    public MapReporter(final Map map) {
+        this.map = map;
+    }
+
+    public void printMap() {
+        for (final Entry entry : this.map.entrySet()) {
+            System.out.println(entry.getKey() + " " + entry.getValue());
+        }
+    }
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Address.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Address.java
new file mode 100644
index 0000000000..410758405e
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Address.java
@@ -0,0 +1,32 @@
+package com.baeldung.nestedhashmaps;
+
+public class Address {
+
+    private Integer addressId;
+    private String addressLocation;
+
+    public Address() {
+    }
+
+    public Address(Integer addressId, String addressLocation) {
+        this.addressId = addressId;
+        this.addressLocation = addressLocation;
+    }
+
+    public Integer getAddressId() {
+        return addressId;
+    }
+
+    public void setAddressId(Integer addressId) {
+        this.addressId = addressId;
+    }
+
+    public String getAddressLocation() {
+        return addressLocation;
+    }
+
+    public void setAddressLocation(String addressLocation) {
+        this.addressLocation = addressLocation;
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Employee.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Employee.java
new file mode 100644
index 0000000000..2ab54ff17c
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/Employee.java
@@ -0,0 +1,43 @@
+package com.baeldung.nestedhashmaps;
+
+public class Employee {
+
+    private Integer employeeId;
+    private Address address;
+    private String employeeName;
+
+    public Employee() {
+        super();
+    }
+
+    public Employee(Integer employeeId, Address address, String employeeName) {
+        this.employeeId = employeeId;
+        this.address = address;
+        this.employeeName = employeeName;
+    }
+
+    public Integer getEmployeeId() {
+        return employeeId;
+    }
+
+    public void setEmployeeId(Integer employeeId) {
+        this.employeeId = employeeId;
+    }
+
+    public Address getAddress() {
+        return address;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+
+    public String getEmployeeName() {
+        return employeeName;
+    }
+
+    public void setEmployeeName(String employeeName) {
+        this.employeeName = employeeName;
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/MapsUtil.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/MapsUtil.java
new file mode 100644
index 0000000000..53781b0bc1
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/MapsUtil.java
@@ -0,0 +1,57 @@
+package com.baeldung.nestedhashmaps;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+public class MapsUtil {
+
+    MapsUtil() {
+        super();
+    }
+
+    public Map buildInnerMap(List batterList) {
+        Map innerBatterMap = new HashMap();
+
+        int index = 1;
+        for (String item : batterList) {
+            innerBatterMap.put(index, item);
+            index++;
+        }
+
+        return innerBatterMap;
+    }
+
+    public Map> createNestedMapfromStream(List listEmployee) {
+        Map> employeeAddressMap = listEmployee.stream()
+                .collect(Collectors.groupingBy(e -> e.getAddress().getAddressId(),
+                        Collectors.toMap(f -> f.getAddress().getAddressLocation(), Employee::getEmployeeName)));
+        return employeeAddressMap;
+    }
+
+    public Map> createNestedObjectMap(List listEmployee) {
+        Map> employeeMap = new HashMap<>();
+
+        employeeMap = listEmployee.stream().collect(Collectors.groupingBy((Employee emp) -> emp.getEmployeeId(),
+                Collectors.toMap((Employee emp) -> emp.getAddress().getAddressId(), fEmpObj -> fEmpObj.getAddress())));
+
+        return employeeMap;
+    }
+
+    public Map flattenMap(Map source) {
+        Map converted = new HashMap<>();
+
+        for (Entry entry : source.entrySet()) {
+            if (entry.getValue() instanceof Map) {
+                flattenMap((Map) entry.getValue())
+                        .forEach((key, value) -> converted.put(entry.getKey() + "." + key, value));
+            } else {
+                converted.put(entry.getKey().toString(), entry.getValue().toString());
+            }
+        }
+        return converted;
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClass.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClass.java
new file mode 100644
index 0000000000..ce63b72527
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClass.java
@@ -0,0 +1,118 @@
+package com.baeldung.nestedhashmaps;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import java.util.List;
+
+public class NestedHashMapExamplesClass {
+    public static void main(String[] args) {
+
+        MapsUtil mUtil = new MapsUtil();
+
+        List batterList = new ArrayList<>();
+        Map> outerBakedGoodsMap = new HashMap<>();
+        Map> outerBakedGoodsMap2 = new HashMap<>();
+        Map> outerBakedGoodsMap3 = new HashMap<>();
+        Map> outerBakedGoodsMap4 = new HashMap<>();
+
+        batterList.add("Mulberry");
+        batterList.add("Cranberry");
+        batterList.add("Blackberry");
+        batterList.add("Mixed fruit");
+        batterList.add("Orange");
+
+        outerBakedGoodsMap.put("Cake", mUtil.buildInnerMap(batterList));
+
+        batterList.clear();
+        batterList.add("Candy");
+        batterList.add("Dark Chocolate");
+        batterList.add("Chocolate");
+        batterList.add("Jam filled");
+        batterList.add("Pineapple");
+
+        outerBakedGoodsMap.put("Donut", mUtil.buildInnerMap(batterList));
+
+        outerBakedGoodsMap2.put("Eclair", mUtil.buildInnerMap(batterList));
+        outerBakedGoodsMap2.put("Donut", mUtil.buildInnerMap(batterList));
+
+        outerBakedGoodsMap3.put("Cake", mUtil.buildInnerMap(batterList));
+        batterList.clear();
+        batterList.add("Banana");
+        batterList.add("Red Velvet");
+        batterList.add("Blackberry");
+        batterList.add("Passion fruit");
+        batterList.add("Kiwi");
+
+        outerBakedGoodsMap3.put("Donut", mUtil.buildInnerMap(batterList));
+
+        outerBakedGoodsMap4.putAll(outerBakedGoodsMap);
+
+        System.out.println(outerBakedGoodsMap.equals(outerBakedGoodsMap2));
+        System.out.println(outerBakedGoodsMap.equals(outerBakedGoodsMap3));
+        System.out.println(outerBakedGoodsMap.equals(outerBakedGoodsMap4));
+
+        outerBakedGoodsMap.get("Cake")
+            .put(6, "Cranberry");
+        System.out.println(outerBakedGoodsMap);
+
+        outerBakedGoodsMap.get("Cake")
+            .remove(5);
+        System.out.println(outerBakedGoodsMap);
+
+        outerBakedGoodsMap.put("Eclair", new HashMap() {
+            {
+                put(1, "Dark Chocolate");
+            }
+        });
+
+        System.out.println(outerBakedGoodsMap);
+        outerBakedGoodsMap.remove("Eclair");
+        System.out.println(outerBakedGoodsMap);
+        System.out.println("Baked Goods Map Flattened: " + mUtil.flattenMap(outerBakedGoodsMap));
+
+        // Employees Map
+        List listEmployee = new ArrayList();
+
+        listEmployee.add(new Employee(1, new Address(124, "Timbuktoo"), "Thorin Oakenshield"));
+        listEmployee.add(new Employee(2, new Address(100, "Misty Lanes"), "Balin"));
+        listEmployee.add(new Employee(3, new Address(156, "Bramles Lane"), "Bofur"));
+        listEmployee.add(new Employee(4, new Address(200, "Bag End"), "Bilbo Baggins"));
+        listEmployee.add(new Employee(5, new Address(23, "Rivendell"), "Elrond"));
+
+        Map> employeeAddressMap = mUtil.createNestedMapfromStream(listEmployee);
+
+        Map> employeeMap = mUtil.createNestedObjectMap(listEmployee);
+        Map> employeeMap2 = mUtil.createNestedObjectMap(listEmployee);
+
+        listEmployee.clear();
+        listEmployee.add(new Employee(1, new Address(500, "Timbuktoo"), "Thorin Oakenshield"));
+        listEmployee.add(new Employee(2, new Address(600, "Misty Lanes"), "Balin"));
+        listEmployee.add(new Employee(3, new Address(700, "Bramles Lane"), "Bofur"));
+        listEmployee.add(new Employee(4, new Address(800, "Bag End"), "Bilbo Baggins"));
+        listEmployee.add(new Employee(5, new Address(900, "Rivendell"), "Elrond"));
+
+        Map> employeeAddressMap1 = mUtil.createNestedMapfromStream(listEmployee);
+
+        Map> employeeMap1 = mUtil.createNestedObjectMap(listEmployee);
+
+        System.out.println(employeeMap.equals(employeeMap1));
+        System.out.println(employeeMap.equals(employeeMap2));
+
+        for (Map.Entry> outerBakedGoodsMapEntrySet : outerBakedGoodsMap.entrySet()) {
+            Map valueMap = outerBakedGoodsMapEntrySet.getValue();
+            System.out.println(valueMap.entrySet());
+        }
+
+        for (Map.Entry> employeeEntrySet : employeeAddressMap.entrySet()) {
+            Map valueMap = employeeEntrySet.getValue();
+            System.out.println(valueMap.entrySet());
+        }
+
+        System.out.println("Employee Address Map Flattened: " + mUtil.flattenMap(employeeAddressMap));
+
+        System.out.println(employeeAddressMap.equals(employeeAddressMap1));
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/HashMapPrinterUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/HashMapPrinterUnitTest.java
new file mode 100644
index 0000000000..e1147f6e00
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/HashMapPrinterUnitTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.mapandhashmap.printer;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class HashMapPrinterUnitTest {
+
+    private final HashMapPrinter mapPrinter = new HashMapPrinter();
+    private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
+
+    @BeforeEach
+    public void setUp() {
+        System.setOut(new PrintStream(outputStreamCaptor));
+    }
+
+    @Test
+    @DisplayName("Test hash map printer with HashMap")
+    void testPrintHashMap() {
+        // given
+        String key = "HashMap";
+        String value = "Main default implementation for the Map interface";
+        String expected = key + " " + value;
+        HashMap map = new HashMap<>();
+        map.put(key, value);
+        // when
+        mapPrinter.printMap(map);
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+
+    }
+
+    @Test
+    @DisplayName("Test hash map printer with LinkedHash")
+    void testPrintLinkedHashMap() {
+        // given
+        String key = "LinkedHashMap";
+        String value = "Use this implementation if you need keep the order of elements";
+        String expected = key + " " + value;
+        LinkedHashMap map = new LinkedHashMap<>();
+        map.put(key, value);
+        // when
+        mapPrinter.printMap(map);
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapPrinterUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapPrinterUnitTest.java
new file mode 100644
index 0000000000..8c45758bdf
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapPrinterUnitTest.java
@@ -0,0 +1,71 @@
+package com.baeldung.mapandhashmap.printer;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.TreeMap;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class MapPrinterUnitTest {
+
+    private final MapPrinter mapPrinter = new MapPrinter();
+    private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
+
+    @BeforeEach
+    public void setUp() {
+        System.setOut(new PrintStream(outputStreamCaptor));
+    }
+
+    @Test
+    @DisplayName("Test printer with TreeMap")
+    void testPrintTreeMap() {
+        // given
+        String key = "TreeMap";
+        String value = "Used when sorting is needed";
+        String expected = key + " " + value;
+        TreeMap map = new TreeMap<>();
+        map.put(key, value);
+        // when
+        mapPrinter.printMap(map);
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    @DisplayName("Test printer with HashMap")
+    void testPrintHashMap() {
+        // given
+        String key = "HashMap";
+        String value = "Main default implementation for the Map interface";
+        String expected = key + " " + value;
+        HashMap map = new HashMap<>();
+        map.put(key, value);
+        // when
+        mapPrinter.printMap(map);
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    @DisplayName("Test printer with LinkedHash")
+    void testPrintLinkedHashMap() {
+        // given
+        String key = "LinkedHashMap";
+        String value = "Use this implementation if you need keep the order of elements";
+        String expected = key + " " + value;
+        LinkedHashMap map = new LinkedHashMap<>();
+        map.put(key, value);
+        // when
+        mapPrinter.printMap(map);
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapReporterUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapReporterUnitTest.java
new file mode 100644
index 0000000000..8f858a75c4
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/mapandhashmap/printer/MapReporterUnitTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.mapandhashmap.printer;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.TreeMap;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class MapReporterUnitTest {
+
+    private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
+
+    @BeforeEach
+    public void setUp() {
+        System.setOut(new PrintStream(outputStreamCaptor));
+    }
+
+    @Test
+    @DisplayName("Test reporter with TreeMap")
+    void testPrintTreeMap() {
+        // given
+        String key = "TreeMap";
+        String value = "Used when sorting is needed";
+        String expected = key + " " + value;
+        TreeMap map = new TreeMap<>();
+        map.put(key, value);
+        // when
+        MapReporter mapReporter = new MapReporter(map);
+        mapReporter.printMap();
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    @DisplayName("Test reporter with HashMap")
+    void testPrintHashMap() {
+        // given
+        String key = "HashMap";
+        String value = "Main default implementation for the Map interface";
+        String expected = key + " " + value;
+        HashMap map = new HashMap<>();
+        map.put(key, value);
+        // when
+        MapReporter mapReporter = new MapReporter(map);
+        mapReporter.printMap();
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    @DisplayName("Test reporter with LinkedHash")
+    void testPrintLinkedHashMap() {
+        // given
+        String key = "LinkedHashMap";
+        String value = "Use this implementation if you need keep the order of elements";
+        String expected = key + " " + value;
+        LinkedHashMap map = new LinkedHashMap<>();
+        map.put(key, value);
+        // when
+        MapReporter mapReporter = new MapReporter(map);
+        mapReporter.printMap();
+        // then
+        String actual = outputStreamCaptor.toString().trim();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClassUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClassUnitTest.java
new file mode 100644
index 0000000000..a86e329bea
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/nestedhashmaps/NestedHashMapExamplesClassUnitTest.java
@@ -0,0 +1,243 @@
+package com.baeldung.nestedhashmaps;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
+import org.hamcrest.collection.IsMapContaining;
+
+public class NestedHashMapExamplesClassUnitTest {
+    private MapsUtil mUtil = new MapsUtil();
+    private List batterList = new ArrayList<>();
+    private List listEmployee = new ArrayList();
+    private Map> actualBakedGoodsMap = new HashMap<>();
+    private Map> actualEmployeeAddressMap = new HashMap<>();
+    private Map> actualEmployeeMap = new HashMap<>();
+
+    @Test
+    public void whenCreateNestedHashMap_thenNestedMap() {
+        assertThat(mUtil.buildInnerMap(batterList), is(notNullValue()));
+        Assert.assertEquals(actualBakedGoodsMap.keySet().size(), 2);
+        Assert.assertThat(actualBakedGoodsMap, IsMapContaining.hasValue(equalTo(mUtil.buildInnerMap(batterList))));
+    }
+
+    private Map> setup() {
+        Map> expectedMap = new HashMap<>();
+        expectedMap.put(Integer.valueOf(100), new HashMap() {
+            {
+                put("Misty Lanes", "Balin");
+            }
+        });
+        expectedMap.put(Integer.valueOf(200), new HashMap() {
+            {
+                put("Bag End", "Bilbo Baggins");
+            }
+        });
+        expectedMap.put(Integer.valueOf(156), new HashMap() {
+            {
+                put("Brambles Lane", "Bofur");
+            }
+        });
+        expectedMap.put(Integer.valueOf(124), new HashMap() {
+            {
+                put("Timbuktoo", "Thorin Oakenshield");
+            }
+        });
+        expectedMap.put(Integer.valueOf(23), new HashMap() {
+            {
+                put("Rivendell", "Elrond");
+            }
+        });
+
+        return expectedMap;
+    }
+
+    @Test
+    public void whenCreateNestedHashMapwithStreams_thenNestedMap() {
+
+        Map> expectedMap = setup();
+
+        assertThat(actualEmployeeAddressMap, equalTo(expectedMap));
+    }
+
+    @Test
+    public void whenCompareTwoHashMapswithDifferenctValues_usingEquals_thenFail() {
+        Map> outerBakedGoodsMap2 = new HashMap<>();
+        outerBakedGoodsMap2.put("Eclair", mUtil.buildInnerMap(batterList));
+        outerBakedGoodsMap2.put("Donut", mUtil.buildInnerMap(batterList));
+        assertNotEquals(outerBakedGoodsMap2, actualBakedGoodsMap);
+
+        Map> outerBakedGoodsMap3 = new HashMap>();
+        outerBakedGoodsMap3.put("Cake", mUtil.buildInnerMap(batterList));
+        batterList = new ArrayList<>();
+        batterList = Arrays.asList("Banana", "Red Velvet", "Blackberry", "Passion fruit", "Kiwi");
+
+        outerBakedGoodsMap3.put("Donut", mUtil.buildInnerMap(batterList));
+
+        assertNotEquals(outerBakedGoodsMap2, actualBakedGoodsMap);
+
+        listEmployee.clear();
+        listEmployee.add(new Employee(1, new Address(500, "Timbuktoo"), "Thorin Oakenshield"));
+        listEmployee.add(new Employee(2, new Address(600, "Misty Lanes"), "Balin"));
+        listEmployee.add(new Employee(3, new Address(700, "Bramles Lane"), "Bofur"));
+        listEmployee.add(new Employee(4, new Address(800, "Bag End"), "Bilbo Baggins"));
+        listEmployee.add(new Employee(5, new Address(900, "Rivendell"), "Elrond"));
+
+        Map> employeeAddressMap1 = mUtil.createNestedMapfromStream(listEmployee);
+
+        Map> employeeMap1 = mUtil.createNestedObjectMap(listEmployee);
+
+        assertNotEquals(employeeAddressMap1, actualEmployeeAddressMap);
+
+        assertNotEquals(employeeMap1, actualEmployeeMap);
+    }
+
+    @Test
+    public void whencomparingDifferentObjectValuesUsingEquals_thenFail() {
+        listEmployee.clear();
+        listEmployee.add(new Employee(1, new Address(124, "Timbuktoo"), "Thorin Oakenshield"));
+        listEmployee.add(new Employee(2, new Address(100, "Misty Lanes"), "Balin"));
+        listEmployee.add(new Employee(3, new Address(156, "Brambles Lane"), "Bofur"));
+        listEmployee.add(new Employee(4, new Address(200, "Bag End"), "Bilbo Baggins"));
+        listEmployee.add(new Employee(5, new Address(23, "Rivendell"), "Elrond"));
+
+        Map> employeeMap1 = listEmployee.stream().collect(Collectors.groupingBy(
+                (Employee emp) -> emp.getEmployeeId(),
+                Collectors.toMap((Employee emp) -> emp.getAddress().getAddressId(), fEmpObj -> fEmpObj.getAddress())));
+
+        assertNotSame(employeeMap1, actualEmployeeMap);
+        assertNotEquals(employeeMap1, actualEmployeeMap);
+
+        Map> expectedMap = setupAddressObjectMap();
+        assertNotSame(expectedMap, actualEmployeeMap);
+        assertNotEquals(expectedMap, actualEmployeeMap);
+
+    }
+
+    @Test
+    public void whenCompareTwoHashMapsUsingEquals_thenSuccess() {
+        Map> outerBakedGoodsMap4 = new HashMap<>();
+        outerBakedGoodsMap4.putAll(actualBakedGoodsMap);
+
+        assertEquals(actualBakedGoodsMap, outerBakedGoodsMap4);
+
+        Map> employeeMap1 = new HashMap<>();
+        employeeMap1.putAll(actualEmployeeMap);
+        assertEquals(actualEmployeeMap, employeeMap1);
+    }
+
+    @Test
+    public void whenAddElementinHashMaps_thenSuccess() {
+        assertEquals(actualBakedGoodsMap.get("Cake").size(), 5);
+        actualBakedGoodsMap.get("Cake").put(6, "Cranberry");
+        assertEquals(actualBakedGoodsMap.get("Cake").size(), 6);
+    }
+
+    @Test
+    public void whenDeleteElementinHashMaps_thenSuccess() {
+        assertNotEquals(actualBakedGoodsMap.get("Cake").get(5), null);
+        actualBakedGoodsMap.get("Cake").remove(5);
+        assertEquals(actualBakedGoodsMap.get("Cake").get(5), null);
+
+        actualBakedGoodsMap.put("Eclair", new HashMap() {
+            {
+                put(1, "Dark Chocolate");
+            }
+        });
+
+        assertNotEquals(actualBakedGoodsMap.get("Eclair").get(1), null);
+        actualBakedGoodsMap.get("Eclair").remove(1);
+        assertEquals(actualBakedGoodsMap.get("Eclair").get(1), null);
+
+        actualBakedGoodsMap.put("Eclair", new HashMap() {
+            {
+                put(1, "Dark Chocolate");
+            }
+        });
+
+        assertNotEquals(actualBakedGoodsMap.get("Eclair"), null);
+        actualBakedGoodsMap.remove("Eclair");
+        assertEquals(actualBakedGoodsMap.get("Eclair"), null);
+    }
+
+    @Test
+    public void whenFlattenMap_thenRemovesNesting() {
+
+        Map flattenedBakedGoodsMap = mUtil.flattenMap(actualBakedGoodsMap);
+        assertThat(flattenedBakedGoodsMap, IsMapContaining.hasKey("Donut.2"));
+
+        Map flattenedEmployeeAddressMap = mUtil.flattenMap(actualEmployeeAddressMap);
+        assertThat(flattenedEmployeeAddressMap, IsMapContaining.hasKey("200.Bag End"));
+    }
+
+    @Before
+    public void buildMaps() {
+
+        batterList = Arrays.asList("Mulberry", "Cranberry", "Blackberry", "Mixed fruit", "Orange");
+
+        actualBakedGoodsMap.put("Cake", mUtil.buildInnerMap(batterList));
+
+        batterList = new ArrayList<>();
+        batterList = Arrays.asList("Candy", "Dark Chocolate", "Chocolate", "Jam filled", "Pineapple");
+
+        actualBakedGoodsMap.put("Donut", mUtil.buildInnerMap(batterList));
+
+        listEmployee.add(new Employee(1, new Address(124, "Timbuktoo"), "Thorin Oakenshield"));
+        listEmployee.add(new Employee(2, new Address(100, "Misty Lanes"), "Balin"));
+        listEmployee.add(new Employee(3, new Address(156, "Brambles Lane"), "Bofur"));
+        listEmployee.add(new Employee(4, new Address(200, "Bag End"), "Bilbo Baggins"));
+        listEmployee.add(new Employee(5, new Address(23, "Rivendell"), "Elrond"));
+
+        actualEmployeeAddressMap = mUtil.createNestedMapfromStream(listEmployee);
+
+        actualEmployeeMap = mUtil.createNestedObjectMap(listEmployee);
+
+    }
+
+    private Map> setupAddressObjectMap() {
+
+        Map> expectedMap = new HashMap<>();
+
+        expectedMap.put(1, new HashMap() {
+            {
+                put(124, new Address(124, "Timbuktoo"));
+            }
+        });
+        expectedMap.put(2, new HashMap() {
+            {
+                put(100, new Address(100, "Misty Lanes"));
+            }
+        });
+        expectedMap.put(3, new HashMap() {
+            {
+                put(156, new Address(156, "Brambles Lane"));
+            }
+        });
+        expectedMap.put(4, new HashMap() {
+            {
+                put(200, new Address(200, "Bag End"));
+            }
+        });
+        expectedMap.put(5, new HashMap() {
+            {
+                put(23, new Address(23, "Rivendell"));
+            }
+        });
+        return expectedMap;
+    }
+
+}
diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml
index 245c4b04bb..34b878df53 100644
--- a/core-java-modules/core-java-collections-maps/pom.xml
+++ b/core-java-modules/core-java-collections-maps/pom.xml
@@ -20,17 +20,6 @@
             commons-collections4
             ${commons-collections4.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        4.1
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-set/pom.xml b/core-java-modules/core-java-collections-set/pom.xml
index b8940f4a68..0b6e324c78 100644
--- a/core-java-modules/core-java-collections-set/pom.xml
+++ b/core-java-modules/core-java-collections-set/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -50,7 +49,6 @@
     
         11
         11
-        4.3
         2.8.5
     
 
diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md
index 12e3c5ac17..574f61ac6a 100644
--- a/core-java-modules/core-java-collections/README.md
+++ b/core-java-modules/core-java-collections/README.md
@@ -12,4 +12,5 @@ This module contains articles about Java collections
 - [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack)
 - [Guide to the Java Queue Interface](https://www.baeldung.com/java-queue)
 - [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections)
-- [[More -->]](/core-java-modules/core-java-collections-2)
+- [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list)
+- More articles: [[next -->]](/core-java-modules/core-java-collections-2)
diff --git a/core-java-modules/core-java-collections/pom.xml b/core-java-modules/core-java-collections/pom.xml
index 8fbc6e8de7..eab7a35584 100644
--- a/core-java-modules/core-java-collections/pom.xml
+++ b/core-java-modules/core-java-collections/pom.xml
@@ -15,12 +15,6 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.openjdk.jmh
             jmh-core
@@ -31,10 +25,11 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
+        
+            org.apache.commons
+            commons-lang3
+            ${commons-lang3.version}
+        
     
 
-    
-        3.11.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java
similarity index 95%
rename from core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java
rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java
index f7be99abdc..1e6efb7840 100644
--- a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java
+++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java
@@ -1,13 +1,15 @@
-package com.baeldung.collections.iterators;
+package com.baeldung.collections.convertarrayprimitives;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import com.google.common.primitives.Ints;
+
 import org.apache.commons.lang3.ArrayUtils;
 
+import com.google.common.primitives.Ints;
+
 public class ConvertPrimitivesArrayToList {
 
     public static void failConvert() {
diff --git a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java
similarity index 87%
rename from core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java
rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java
index b773baf7d8..f9f5f8ea91 100644
--- a/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java
+++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java
@@ -1,14 +1,11 @@
-package com.baeldung.collections.iterators;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-import com.google.common.primitives.Ints;
-import org.junit.Test;
+package com.baeldung.collections.convertarrayprimitives;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.Arrays;
+
+import org.junit.Test;
+
 public class ConvertPrimitivesArrayToListUnitTest {
 
     @Test
diff --git a/core-java-modules/core-java-concurrency-2/pom.xml b/core-java-modules/core-java-concurrency-2/pom.xml
index b8a1d641d4..c61f28a6b3 100644
--- a/core-java-modules/core-java-concurrency-2/pom.xml
+++ b/core-java-modules/core-java-concurrency-2/pom.xml
@@ -15,11 +15,6 @@
     
 
     
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
         
             com.googlecode.thread-weaver
             threadweaver
@@ -31,6 +26,12 @@
             tempus-fugit
             ${tempus-fugit.version}
             test
+            
+                
+                    junit
+                    junit
+                
+            
         
         
             com.googlecode.multithreadedtc
diff --git a/core-java-modules/core-java-concurrency-advanced-2/pom.xml b/core-java-modules/core-java-concurrency-advanced-2/pom.xml
index 93c23ccae7..1f19dc8cca 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/pom.xml
+++ b/core-java-modules/core-java-concurrency-advanced-2/pom.xml
@@ -30,12 +30,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -48,8 +42,4 @@
         
     
 
-    
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java b/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
index 9900d1c63d..b0866cb7f0 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
@@ -1,9 +1,15 @@
 package com.baeldung.concurrent.prioritytaskexecution;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class Job implements Runnable {
-    private String jobName;
-    private JobPriority jobPriority;
-    
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(Job.class);
+
+    private final String jobName;
+    private final JobPriority jobPriority;
+
     public Job(String jobName, JobPriority jobPriority) {
         this.jobName = jobName;
         this.jobPriority = jobPriority != null ? jobPriority : JobPriority.MEDIUM;
@@ -16,8 +22,7 @@ public class Job implements Runnable {
     @Override
     public void run() {
         try {
-            System.out.println("Job:" + jobName + 
-              " Priority:" + jobPriority);
+            LOGGER.debug("Job:{} Priority:{}", jobName, jobPriority);
             Thread.sleep(1000);
         } catch (InterruptedException ignored) {
         }
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java b/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
index ebe59e33b1..26d620ba07 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
@@ -1,19 +1,21 @@
 package com.baeldung.forkjoin;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ForkJoinTask;
 import java.util.concurrent.RecursiveAction;
-import java.util.logging.Logger;
 
 public class CustomRecursiveAction extends RecursiveAction {
 
+    final Logger logger = LoggerFactory.getLogger(CustomRecursiveAction.class);
+
     private String workLoad = "";
     private static final int THRESHOLD = 4;
 
-    private static Logger logger = Logger.getAnonymousLogger();
-
     public CustomRecursiveAction(String workLoad) {
         this.workLoad = workLoad;
     }
@@ -43,7 +45,7 @@ public class CustomRecursiveAction extends RecursiveAction {
 
     private void processing(String work) {
         String result = work.toUpperCase();
-        logger.info("This result - (" + result + ") - was processed by " + Thread.currentThread()
+        logger.debug("This result - (" + result + ") - was processed by " + Thread.currentThread()
             .getName());
     }
 }
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
index 1e67fe45c1..20e6a5ef5b 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
@@ -3,9 +3,9 @@ package com.baeldung.concurrent.prioritytaskexecution;
 import org.junit.Test;
 
 public class PriorityJobSchedulerUnitTest {
-    private static int POOL_SIZE = 1;
-    private static int QUEUE_SIZE = 10;
-    
+    private static final int POOL_SIZE = 1;
+    private static final int QUEUE_SIZE = 10;
+
     @Test
     public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked() {
         Job job1 = new Job("Job1", JobPriority.LOW);
@@ -14,19 +14,19 @@ public class PriorityJobSchedulerUnitTest {
         Job job4 = new Job("Job4", JobPriority.MEDIUM);
         Job job5 = new Job("Job5", JobPriority.LOW);
         Job job6 = new Job("Job6", JobPriority.HIGH);
-        
+
         PriorityJobScheduler pjs = new PriorityJobScheduler(POOL_SIZE, QUEUE_SIZE);
-        
+
         pjs.scheduleJob(job1);
         pjs.scheduleJob(job2);
         pjs.scheduleJob(job3);
         pjs.scheduleJob(job4);
         pjs.scheduleJob(job5);
         pjs.scheduleJob(job6);
-        
+
         // ensure no tasks is pending before closing the scheduler
         while (pjs.getQueuedTaskCount() != 0);
-        
+
         // delay to avoid job sleep (added for demo) being interrupted
         try {
             Thread.sleep(2000);
@@ -34,7 +34,7 @@ public class PriorityJobSchedulerUnitTest {
             Thread.currentThread().interrupt();
             throw new RuntimeException(e);
         }
-        
+
         pjs.closeScheduler();
     }
 }
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/forkjoin/Java8ForkJoinIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/forkjoin/Java8ForkJoinIntegrationTest.java
index c469fe0195..ec10e2be79 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/forkjoin/Java8ForkJoinIntegrationTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/forkjoin/Java8ForkJoinIntegrationTest.java
@@ -1,18 +1,15 @@
 package com.baeldung.forkjoin;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import com.baeldung.forkjoin.util.PoolUtil;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.util.Random;
 import java.util.concurrent.ForkJoinPool;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import com.baeldung.forkjoin.CustomRecursiveAction;
-import com.baeldung.forkjoin.CustomRecursiveTask;
-import com.baeldung.forkjoin.util.PoolUtil;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 public class Java8ForkJoinIntegrationTest {
 
@@ -63,11 +60,11 @@ public class Java8ForkJoinIntegrationTest {
         ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
 
         forkJoinPool.execute(customRecursiveTask);
-        int result = customRecursiveTask.join();
+        customRecursiveTask.join();
         assertTrue(customRecursiveTask.isDone());
 
         forkJoinPool.submit(customRecursiveTask);
-        int resultTwo = customRecursiveTask.join();
+        customRecursiveTask.join();
         assertTrue(customRecursiveTask.isDone());
     }
 
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
index 85cff51eb3..dc30ce6c74 100644
--- a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
@@ -1,12 +1,12 @@
 package com.baeldung.thread.join;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.logging.Logger;
-
 import org.junit.Ignore;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Demonstrates Thread.join behavior.
@@ -14,55 +14,55 @@ import org.junit.Test;
  */
 public class ThreadJoinUnitTest {
 
-    final static Logger LOGGER = Logger.getLogger(ThreadJoinUnitTest.class.getName());
+    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadJoinUnitTest.class);
 
-    class SampleThread extends Thread {
-        public int processingCount = 0;
+    static class SampleThread extends Thread {
+        public int processingCount;
 
         SampleThread(int processingCount) {
             this.processingCount = processingCount;
-            LOGGER.info("Thread " + this.getName() + " created");
+            LOGGER.debug("Thread " + this.getName() + " created");
         }
 
         @Override
         public void run() {
-            LOGGER.info("Thread " + this.getName() + " started");
+            LOGGER.debug("Thread " + this.getName() + " started");
             while (processingCount > 0) {
                 try {
                     Thread.sleep(1000); // Simulate some work being done by thread
                 } catch (InterruptedException e) {
-                    LOGGER.info("Thread " + this.getName() + " interrupted.");
+                    LOGGER.debug("Thread " + this.getName() + " interrupted.");
                 }
                 processingCount--;
-                LOGGER.info("Inside Thread " + this.getName() + ", processingCount = " + processingCount);
+                LOGGER.debug("Inside Thread " + this.getName() + ", processingCount = " + processingCount);
             }
-            LOGGER.info("Thread " + this.getName() + " exiting");
+            LOGGER.debug("Thread " + this.getName() + " exiting");
         }
     }
 
     @Test
     public void givenNewThread_whenJoinCalled_returnsImmediately() throws InterruptedException {
         Thread t1 = new SampleThread(0);
-        LOGGER.info("Invoking join.");
+        LOGGER.debug("Invoking join.");
         t1.join();
-        LOGGER.info("Returned from join");
-        LOGGER.info("Thread state is" + t1.getState());
+        LOGGER.debug("Returned from join");
+        LOGGER.debug("Thread state is" + t1.getState());
         assertFalse(t1.isAlive());
     }
 
     @Test
-    public void givenStartedThread_whenJoinCalled_waitsTillCompletion() 
+    public void givenStartedThread_whenJoinCalled_waitsTillCompletion()
       throws InterruptedException {
         Thread t2 = new SampleThread(1);
         t2.start();
-        LOGGER.info("Invoking join.");
+        LOGGER.debug("Invoking join.");
         t2.join();
-        LOGGER.info("Returned from join");
+        LOGGER.debug("Returned from join");
         assertFalse(t2.isAlive());
     }
 
     @Test
-    public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout() 
+    public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout()
       throws InterruptedException {
         Thread t3 = new SampleThread(10);
         t3.start();
@@ -72,18 +72,18 @@ public class ThreadJoinUnitTest {
 
     @Test
     @Ignore
-    public void givenThreadTerminated_checkForEffect_notGuaranteed() 
+    public void givenThreadTerminated_checkForEffect_notGuaranteed()
       throws InterruptedException {
         SampleThread t4 = new SampleThread(10);
         t4.start();
       //not guaranteed to stop even if t4 finishes.
         do {
-            
-        } while (t4.processingCount > 0);  
+
+        } while (t4.processingCount > 0);
     }
 
     @Test
-    public void givenJoinWithTerminatedThread_checkForEffect_guaranteed() 
+    public void givenJoinWithTerminatedThread_checkForEffect_guaranteed()
       throws InterruptedException {
         SampleThread t4 = new SampleThread(10);
         t4.start();
diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/test/resources/logback.xml b/core-java-modules/core-java-concurrency-advanced-2/src/test/resources/logback.xml
new file mode 100644
index 0000000000..b2fa0488f3
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-advanced-2/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+            
+        
+    
+
+    
+        
+    
+
diff --git a/core-java-modules/core-java-concurrency-advanced-3/pom.xml b/core-java-modules/core-java-concurrency-advanced-3/pom.xml
index 915aa8d912..49a72112b4 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/pom.xml
+++ b/core-java-modules/core-java-concurrency-advanced-3/pom.xml
@@ -15,12 +15,6 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.jcabi
             jcabi-aspects
@@ -32,11 +26,6 @@
             ${aspectjrt.version}
             runtime
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.cactoos
             cactoos
@@ -94,12 +83,10 @@
     
 
     
-        3.14.0
         1.8
         1.8
         0.22.6
         1.9.5
-        28.2-jre
         0.43
         1.2.3
         0.14.1
diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java
index ee1bdcd55b..2af3113549 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java
@@ -3,17 +3,18 @@ package com.baeldung.abaproblem;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
+
 public class Account {
 
-    private AtomicInteger balance;
-    private AtomicInteger transactionCount;
-    private ThreadLocal currentThreadCASFailureCount;
+    private final AtomicInteger balance;
+    private final AtomicInteger transactionCount;
+    private final ThreadLocal currentThreadCASFailureCount;
 
     public Account() {
         this.balance = new AtomicInteger(0);
         this.transactionCount = new AtomicInteger(0);
-        this.currentThreadCASFailureCount = new ThreadLocal<>();
-        this.currentThreadCASFailureCount.set(0);
+        this.currentThreadCASFailureCount = ThreadLocal.withInitial(() -> 0);
     }
 
     public int getBalance() {
@@ -43,11 +44,7 @@ public class Account {
 
     private void maybeWait() {
         if ("thread1".equals(Thread.currentThread().getName())) {
-            try {
-                TimeUnit.SECONDS.sleep(2);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
+            sleepUninterruptibly(2, TimeUnit.SECONDS);
         }
     }
 
diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
index 415b24738a..69aed0b979 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
@@ -1,25 +1,22 @@
 package com.baeldung.atomicstampedreference;
 
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicStampedReference;
 
 public class StampedAccount {
 
-    private AtomicInteger stamp = new AtomicInteger(0);
-    private AtomicStampedReference account = new AtomicStampedReference<>(0, 0);
-
-    public int getBalance() {
-        return account.getReference();
-    }
-
-    public int getStamp() {
-        return account.getStamp();
-    }
+    private final AtomicInteger stamp = new AtomicInteger(0);
+    private final AtomicStampedReference account = new AtomicStampedReference<>(0, 0);
 
     public boolean deposit(int funds) {
         int[] stamps = new int[1];
         int current = this.account.get(stamps);
         int newStamp = this.stamp.incrementAndGet();
+
+        // Thread is paused here to allow other threads to update the stamp and amount (for testing only)
+        sleep();
+
         return this.account.compareAndSet(current, current + funds, stamps[0], newStamp);
     }
 
@@ -29,4 +26,19 @@ public class StampedAccount {
         int newStamp = this.stamp.incrementAndGet();
         return this.account.compareAndSet(current, current - funds, stamps[0], newStamp);
     }
+
+    public int getBalance() {
+        return account.getReference();
+    }
+
+    public int getStamp() {
+        return account.getStamp();
+    }
+
+    private static void sleep() {
+        try {
+            TimeUnit.SECONDS.sleep(1);
+        } catch (InterruptedException ignored) {
+        }
+    }
 }
diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java
index aa5f0f7997..3e188d682e 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java
@@ -1,8 +1,13 @@
 package com.baeldung.abaproblem;
 
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -30,45 +35,39 @@ public class AccountUnitTest {
         assertTrue(account.deposit(moneyToDeposit));
 
         assertEquals(moneyToDeposit, account.getBalance());
+        assertEquals(1, account.getTransactionCount());
     }
 
     @Test
-    public void withdrawTest() throws InterruptedException {
+    public void withdrawTest() {
         final int defaultBalance = 50;
         final int moneyToWithdraw = 20;
 
         account.deposit(defaultBalance);
 
         assertTrue(account.withdraw(moneyToWithdraw));
-
         assertEquals(defaultBalance - moneyToWithdraw, account.getBalance());
     }
 
     @Test
-    public void abaProblemTest() throws InterruptedException {
+    public void abaProblemTest() throws Exception {
         final int defaultBalance = 50;
 
         final int amountToWithdrawByThread1 = 20;
         final int amountToWithdrawByThread2 = 10;
         final int amountToDepositByThread2 = 10;
 
-        assertEquals(0, account.getTransactionCount());
-        assertEquals(0, account.getCurrentThreadCASFailureCount());
         account.deposit(defaultBalance);
-        assertEquals(1, account.getTransactionCount());
-
-        Thread thread1 = new Thread(() -> {
 
+        Runnable thread1 = () -> {
             // this will take longer due to the name of the thread
             assertTrue(account.withdraw(amountToWithdrawByThread1));
 
             // thread 1 fails to capture ABA problem
             assertNotEquals(1, account.getCurrentThreadCASFailureCount());
+        };
 
-        }, "thread1");
-
-        Thread thread2 = new Thread(() -> {
-
+        Runnable thread2 = () -> {
             assertTrue(account.deposit(amountToDepositByThread2));
             assertEquals(defaultBalance + amountToDepositByThread2, account.getBalance());
 
@@ -79,12 +78,13 @@ public class AccountUnitTest {
             assertEquals(defaultBalance, account.getBalance());
 
             assertEquals(0, account.getCurrentThreadCASFailureCount());
-        }, "thread2");
+        };
 
-        thread1.start();
-        thread2.start();
-        thread1.join();
-        thread2.join();
+        Future future1 = getSingleThreadExecutorService("thread1").submit(thread1);
+        Future future2 = getSingleThreadExecutorService("thread2").submit(thread2);
+
+        future1.get();
+        future2.get();
 
         // compareAndSet operation succeeds for thread 1
         assertEquals(defaultBalance - amountToWithdrawByThread1, account.getBalance());
@@ -95,4 +95,10 @@ public class AccountUnitTest {
         // thread 2 did two modifications as well
         assertEquals(4, account.getTransactionCount());
     }
+
+    private static ExecutorService getSingleThreadExecutorService(String threadName) {
+        return Executors.newSingleThreadExecutor(
+          new ThreadFactoryBuilder().setNameFormat(threadName).build()
+        );
+    }
 }
diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java
index ce83355073..2840c25cf6 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java
@@ -1,21 +1,38 @@
 package com.baeldung.atomicstampedreference;
 
-import org.junit.Assert;
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 public class ThreadStampedAccountUnitTest {
 
     @Test
     public void givenMultiThread_whenStampedAccount_thenSetBalance() throws InterruptedException {
         StampedAccount account = new StampedAccount();
+
         Thread t = new Thread(() -> {
-            while (!account.withdrawal(100))
+            while (!account.deposit(100)) {
                 Thread.yield();
+            }
         });
         t.start();
-        Assert.assertTrue(account.deposit(100));
-        t.join(1_000);
-        Assert.assertFalse(t.isAlive());
-        Assert.assertSame(0, account.getBalance());
+
+        Thread t2 = new Thread(() -> {
+            while (!account.withdrawal(100)) {
+                Thread.yield();
+            }
+        });
+        t2.start();
+
+        t.join(10_000);
+        t2.join(10_000);
+
+        assertFalse(t.isAlive());
+        assertFalse(t2.isAlive());
+
+        assertEquals(0, account.getBalance());
+        assertTrue(account.getStamp() > 0);
     }
 }
diff --git a/core-java-modules/core-java-concurrency-advanced-4/README.md b/core-java-modules/core-java-concurrency-advanced-4/README.md
index db856a2cd6..446a553b88 100644
--- a/core-java-modules/core-java-concurrency-advanced-4/README.md
+++ b/core-java-modules/core-java-concurrency-advanced-4/README.md
@@ -3,3 +3,4 @@
 - [Binary Semaphore vs Reentrant Lock](https://www.baeldung.com/java-binary-semaphore-vs-reentrant-lock)
 - [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices)
 - [Start Two Threads at the Exact Same Time in Java](https://www.baeldung.com/java-start-two-threads-at-same-time)
+- [Volatile Variables and Thread Safety](https://www.baeldung.com/java-volatile-variables-thread-safety)
diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/volatilekeywordthreadsafety/VolatileVarNotThreadSafe.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/volatilekeywordthreadsafety/VolatileVarNotThreadSafe.java
new file mode 100644
index 0000000000..cf9b7fd20b
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/volatilekeywordthreadsafety/VolatileVarNotThreadSafe.java
@@ -0,0 +1,47 @@
+package com.baeldung.volatilekeywordthreadsafety;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+public class VolatileVarNotThreadSafe {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VolatileVarNotThreadSafe.class);
+    private static volatile int count = 0;
+    private static final int MAX_LIMIT = 1000;
+    
+    public static void increment() {
+        count++;
+    }
+    
+    public static int getCount() {
+        return count;
+    }
+    
+    public static void main(String[] args) throws InterruptedException {
+        Thread t1 = new Thread(new Runnable() {
+           @Override
+           public void run() {
+               for(int index=0; index 0);
+    }
+}
diff --git a/core-java-modules/core-java-concurrency-advanced/pom.xml b/core-java-modules/core-java-concurrency-advanced/pom.xml
index 3c21b49ae5..3c726e1284 100644
--- a/core-java-modules/core-java-concurrency-advanced/pom.xml
+++ b/core-java-modules/core-java-concurrency-advanced/pom.xml
@@ -35,12 +35,6 @@
             commons-math3
             ${commons-math3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.jayway.awaitility
             awaitility
@@ -60,13 +54,8 @@
     
 
     
-        
-        21.0
         3.6.1
-        4.1
         4.01
-        
-        3.6.1
         1.7.0
     
 
diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
index dd1487b5cb..c022c02085 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
+++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
@@ -16,12 +16,17 @@ class LongRunningAction implements Runnable {
     public void run() {
         System.out.println("This is phase " + ph.getPhase());
         System.out.println("Thread " + threadName + " before long running action");
-        ph.arriveAndAwaitAdvance();
+        
         try {
-            Thread.sleep(20);
+            Thread.sleep(2000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
+        
+        System.out.println("Thread " + threadName + " action completed and waiting for others");
+        ph.arriveAndAwaitAdvance();
+        System.out.println("Thread " + threadName + " proceeding in phase " + ph.getPhase());
+        
         ph.arriveAndDeregister();
     }
 }
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
index a7b56e1151..88c18b5149 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
+++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
@@ -26,13 +26,20 @@ public class PhaserUnitTest {
         executorService.submit(new LongRunningAction("thread-3", ph));
 
         //then
+        System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
         ph.arriveAndAwaitAdvance();
+        System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
+        
         assertEquals(1, ph.getPhase());
 
         //and
         executorService.submit(new LongRunningAction("thread-4", ph));
         executorService.submit(new LongRunningAction("thread-5", ph));
+        
+        System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
         ph.arriveAndAwaitAdvance();
+        System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
+        
         assertEquals(2, ph.getPhase());
 
 
diff --git a/core-java-modules/core-java-concurrency-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md
index d2ff75ca95..af46046709 100644
--- a/core-java-modules/core-java-concurrency-basic-2/README.md
+++ b/core-java-modules/core-java-concurrency-basic-2/README.md
@@ -12,6 +12,6 @@ This module contains articles about basic Java concurrency
 - [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference)
 - [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe)
 - [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time)
-- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
 - [How to Get the Number of Threads in a Java Process](https://www.baeldung.com/java-get-number-of-threads)
-- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic)
+- [Set the Name of a Thread in Java](https://www.baeldung.com/java-set-thread-name)
+- [[<-- Prev]](../core-java-concurrency-basic)[[Next -->]](../core-java-concurrency-basic-3)
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threads/name/CustomThreadName.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threads/name/CustomThreadName.java
new file mode 100644
index 0000000000..9ce35d1137
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threads/name/CustomThreadName.java
@@ -0,0 +1,70 @@
+package com.baeldung.concurrent.threads.name;
+
+public class CustomThreadName {
+
+    public int currentNumber = 1;
+
+    public int N = 5;
+
+    public static void main(String[] args) {
+
+        CustomThreadName test = new CustomThreadName();
+
+        Thread oddThread = new Thread(() -> {
+            test.printOddNumber();
+            // Uncomment below to set thread name using setName() Method
+            // Thread.currentThread().setName("ODD");
+        }, "ODD");
+        // or Uncomment below to set thread name using setName() Method
+        // oddThread.setName("ODD");
+
+        Thread evenThread = new Thread(() -> {
+            test.printEvenNumber();
+            // Uncomment below to set thread name using setName() Method
+            // Thread.currentThread().setName("EVEN");
+        }, "EVEN");
+
+        // evenThread.setName("EVEN");
+
+        evenThread.start();
+        oddThread.start();
+
+    }
+
+    public void printEvenNumber() {
+        synchronized (this) {
+            while (currentNumber < N) {
+                while (currentNumber % 2 == 1) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+                System.out.println(Thread.currentThread()
+                    .getName() + " --> " + currentNumber);
+                currentNumber++;
+                notify();
+            }
+        }
+    }
+
+    public void printOddNumber() {
+        synchronized (this) {
+            while (currentNumber < N) {
+                while (currentNumber % 2 == 0) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+                System.out.println(Thread.currentThread()
+                    .getName() + " --> " + currentNumber);
+                currentNumber++;
+                notify();
+            }
+        }
+    }
+
+}
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
index 9d76c1fcd1..533f4e111d 100644
--- a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
+++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
@@ -17,9 +17,10 @@ public class Data {
             }
         }
         transfer = true;
-
+        
+        String returnPacket = packet;
         notifyAll();
-        return packet;
+        return returnPacket;
     }
  
     public synchronized void send(String packet) {
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-basic-2/src/main/resources/logback.xml
index 56af2d397e..7d900d8ea8 100644
--- a/core-java-modules/core-java-concurrency-basic-2/src/main/resources/logback.xml
+++ b/core-java-modules/core-java-concurrency-basic-2/src/main/resources/logback.xml
@@ -7,12 +7,6 @@
         
     
 
-    
-    
-
-    
-    
-
     
         
     
diff --git a/core-java-modules/core-java-concurrency-basic-3/README.md b/core-java-modules/core-java-concurrency-basic-3/README.md
new file mode 100644
index 0000000000..477f37e00a
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/README.md
@@ -0,0 +1,8 @@
+## Core Java Concurrency Basic
+
+This module contains articles about basic Java concurrency.
+
+### Relevant Articles: 
+
+- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
+- [[<-- Prev]](../core-java-concurrency-basic-2)
diff --git a/core-java-modules/core-java-concurrency-basic-3/pom.xml b/core-java-modules/core-java-concurrency-basic-3/pom.xml
new file mode 100644
index 0000000000..20615e3250
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/pom.xml
@@ -0,0 +1,27 @@
+
+
+    4.0.0
+    core-java-concurrency-basic-3
+    0.1.0-SNAPSHOT
+    core-java-concurrency-basic-3
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        core-java-concurrency-basic-3
+        
+            
+                src/main/resources
+                true
+            
+        
+    
+
+
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java
similarity index 100%
rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java
rename to core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java
similarity index 100%
rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java
rename to core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java
diff --git a/guest/spring-mvc/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-basic-3/src/main/resources/logback.xml
similarity index 100%
rename from guest/spring-mvc/src/main/resources/logback.xml
rename to core-java-modules/core-java-concurrency-basic-3/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java
similarity index 81%
rename from core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java
rename to core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java
index 1ea3f9aa9b..d11ac670f3 100644
--- a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java
+++ b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java
@@ -1,7 +1,7 @@
 package com.baeldung.concurrent.interrupt;
 
-import static org.junit.Assert.assertTrue;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.junit.jupiter.api.Test;
 
@@ -9,23 +9,23 @@ public class InterruptExampleUnitTest {
 
     @Test
     public void whenPropagateException_thenThrowsInterruptedException() {
-        assertThrows(InterruptedException.class, () -> InterruptExample.propagateException());
+        assertThrows(InterruptedException.class, InterruptExample::propagateException);
     }
 
     @Test
     public void whenRestoreTheState_thenReturnsTrue() {
         assertTrue(InterruptExample.restoreTheState());
     }
-    
+
     @Test
     public void whenThrowCustomException_thenContainsExpectedMessage() {
-        Exception exception = assertThrows(CustomInterruptedException.class, () -> InterruptExample.throwCustomException());
+        Exception exception = assertThrows(CustomInterruptedException.class, InterruptExample::throwCustomException);
         String expectedMessage = "This thread was interrupted";
         String actualMessage = exception.getMessage();
 
         assertTrue(actualMessage.contains(expectedMessage));
     }
-   
+
     @Test
     public void whenHandleWithCustomException_thenReturnsTrue() throws CustomInterruptedException{
         assertTrue(InterruptExample.handleWithCustomException());
diff --git a/core-java-modules/core-java-concurrency-basic/pom.xml b/core-java-modules/core-java-concurrency-basic/pom.xml
index 7212a2dcb1..1e3157291a 100644
--- a/core-java-modules/core-java-concurrency-basic/pom.xml
+++ b/core-java-modules/core-java-concurrency-basic/pom.xml
@@ -20,12 +20,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.jayway.awaitility
             awaitility
@@ -45,8 +39,6 @@
     
 
     
-        
-        3.6.1
         1.7.0
     
 
diff --git a/core-java-modules/core-java-concurrency-collections-2/README.md b/core-java-modules/core-java-concurrency-collections-2/README.md
index 6ad6529efc..692c218395 100644
--- a/core-java-modules/core-java-concurrency-collections-2/README.md
+++ b/core-java-modules/core-java-concurrency-collections-2/README.md
@@ -2,4 +2,5 @@
 
 - [Introduction to Lock Striping](https://www.baeldung.com/java-lock-stripping)
 - [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue)
+- [Java Concurrent HashSet Equivalent to ConcurrentHashMap](https://www.baeldung.com/java-concurrent-hashset-concurrenthashmap)
 - [[<-- Prev]](/core-java-modules/core-java-concurrency-collections)
diff --git a/core-java-modules/core-java-concurrency-collections-2/pom.xml b/core-java-modules/core-java-concurrency-collections-2/pom.xml
index 8de0e1bef7..9a95662fae 100644
--- a/core-java-modules/core-java-concurrency-collections-2/pom.xml
+++ b/core-java-modules/core-java-concurrency-collections-2/pom.xml
@@ -14,11 +14,6 @@
     
 
     
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.openjdk.jmh
             jmh-core
@@ -29,18 +24,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        28.2-jre
-        
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashset/ConcurrentHashSetUnitTest.java b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashset/ConcurrentHashSetUnitTest.java
new file mode 100644
index 0000000000..f14a139a02
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashset/ConcurrentHashSetUnitTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.concurrenthashset;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.junit.jupiter.api.Test;
+
+public class ConcurrentHashSetUnitTest {
+
+    @Test
+    public void whenCreateConcurrentHashSetWithStaticMethod_thenSetIsCreated() {
+        // when
+        Set threadSafeUniqueNumbers = ConcurrentHashMap.newKeySet();
+        threadSafeUniqueNumbers.add(23);
+        threadSafeUniqueNumbers.add(45);
+
+        //then
+        assertTrue(threadSafeUniqueNumbers.stream()
+            .anyMatch(entry -> entry.equals(23)));
+        assertTrue(threadSafeUniqueNumbers.stream()
+            .anyMatch(entry -> entry.equals(45)));
+    }
+
+    @Test
+    public void whenCreateConcurrentHashSetWithKeySetMethod_thenSetIsSyncedWithMapped() {
+        // when
+        ConcurrentHashMap numbersMap = new ConcurrentHashMap<>();
+        Set numbersSet = numbersMap.keySet();
+
+        numbersMap.put(1, "One");
+        numbersMap.put(2, "Two");
+        numbersMap.put(3, "Three");
+
+        System.out.println("Map before remove: " + numbersMap);
+        System.out.println("Set before remove: " + numbersSet);
+
+        numbersSet.remove(2);
+
+        System.out.println("Set after remove: " + numbersSet);
+        System.out.println("Map after remove: " + numbersMap);
+
+        //then
+        assertNull(numbersMap.get(2));
+    }
+
+    @Test
+    public void whenCreateConcurrentHashSetWithKeySetMethodDefaultValue_thenSetIsSyncedWithMapped() {
+        // when
+        ConcurrentHashMap numbersMap = new ConcurrentHashMap<>();
+        Set numbersSet = numbersMap.keySet("SET-ENTRY");
+
+        numbersMap.put(1, "One");
+        numbersMap.put(2, "Two");
+        numbersMap.put(3, "Three");
+
+        System.out.println("Map before add: " + numbersMap);
+        System.out.println("Set before add: " + numbersSet);
+
+        numbersSet.addAll(asList(4, 5));
+
+        System.out.println("Map after add: " + numbersMap);
+        System.out.println("Set after add: " + numbersSet);
+
+        //then
+        assertEquals("One", numbersMap.get(1));
+        assertEquals("SET-ENTRY", numbersMap.get(4));
+        assertEquals("SET-ENTRY", numbersMap.get(5));
+    }
+
+    @Test
+    public void whenSynchronizedSetIsCreated_thenSetIsCreated() {
+        // when
+        Set syncNumbers = Collections.synchronizedSet(new HashSet<>());
+        syncNumbers.add(1);
+
+        //then
+        assertTrue(syncNumbers.stream()
+            .anyMatch(entry -> entry.equals(1)));
+    }
+
+    @Test
+    public void whenCopyOnWriteArraySetIsCreated_thenSetIsCreated() {
+        // when
+        Set copyOnArraySet = new CopyOnWriteArraySet<>();
+        copyOnArraySet.add(1);
+
+        //then
+        assertTrue(copyOnArraySet.stream()
+            .anyMatch(entry -> entry.equals(1)));
+    }
+
+}
diff --git a/core-java-modules/core-java-concurrency-collections/pom.xml b/core-java-modules/core-java-concurrency-collections/pom.xml
index f22da1c848..8b8d2fe03b 100644
--- a/core-java-modules/core-java-concurrency-collections/pom.xml
+++ b/core-java-modules/core-java-concurrency-collections/pom.xml
@@ -14,15 +14,6 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-    
-
     
         core-java-concurrency-collections
         
@@ -33,9 +24,4 @@
         
     
 
-    
-        
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-date-operations-1/pom.xml b/core-java-modules/core-java-date-operations-1/pom.xml
index 7b7c68d1b6..ea9f94fa56 100644
--- a/core-java-modules/core-java-date-operations-1/pom.xml
+++ b/core-java-modules/core-java-date-operations-1/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -26,16 +25,11 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
+
         
             com.darwinsys
             hirondelle-date4j
-            RELEASE
+            ${hirondelle-date4j.version}
             test
         
     
@@ -63,8 +57,7 @@
 
     
         2.10
-        
-        3.6.1
+        RELEASE
         1.9
         1.9
     
diff --git a/core-java-modules/core-java-date-operations-2/pom.xml b/core-java-modules/core-java-date-operations-2/pom.xml
index 1d283851ca..f60c7b7fc0 100644
--- a/core-java-modules/core-java-date-operations-2/pom.xml
+++ b/core-java-modules/core-java-date-operations-2/pom.xml
@@ -30,18 +30,11 @@
             hirondelle-date4j
             ${hirondelle-date4j.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
         2.10
         1.5.1
-        3.14.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-datetime-conversion/pom.xml b/core-java-modules/core-java-datetime-conversion/pom.xml
index 8f082e2793..3ff26323df 100644
--- a/core-java-modules/core-java-datetime-conversion/pom.xml
+++ b/core-java-modules/core-java-datetime-conversion/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -31,13 +30,6 @@
             log4j
             ${log4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -63,8 +55,6 @@
 
     
         2.10
-        
-        3.6.1
         1.9
         1.9
     
diff --git a/core-java-modules/core-java-datetime-string/pom.xml b/core-java-modules/core-java-datetime-string/pom.xml
index f50eb2ae5e..2b3c2edb02 100644
--- a/core-java-modules/core-java-datetime-string/pom.xml
+++ b/core-java-modules/core-java-datetime-string/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -32,13 +31,6 @@
             log4j
             ${log4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             joda-time
             joda-time
@@ -47,7 +39,7 @@
         
             com.darwinsys
             hirondelle-date4j
-            RELEASE
+            ${hirondelle-date4j.version}
             test
         
     
@@ -76,8 +68,7 @@
     
         1.6
         2.10.10
-        
-        3.6.1
+        RELEASE
         1.9
         1.9
     
diff --git a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java
index b1c88cb44c..172882af2c 100644
--- a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java
+++ b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java
@@ -12,6 +12,7 @@ import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.format.FormatStyle;
 import java.time.temporal.ChronoUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.util.Locale;
 import java.util.TimeZone;
 
@@ -159,4 +160,35 @@ public class DateTimeFormatterUnitTest {
         DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
         ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15"));
     }
+
+    @Test
+    public void shouldPrintFormattedZonedDateTime() {
+        ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 02, 15, 0, 0, 0, 0, ZoneId.of("Europe/Paris"));
+        String formattedZonedDateTime = DateTimeFormatter.ISO_INSTANT.format(zonedDateTime);
+        
+        Assert.assertEquals("2021-02-14T23:00:00Z", formattedZonedDateTime);
+    }
+    
+    @Test(expected = UnsupportedTemporalTypeException.class)
+    public void shouldExpectAnExceptionIfInputIsLocalDateTime() {
+        DateTimeFormatter.ISO_INSTANT.format(LocalDate.now());
+    }
+    
+    @Test
+    public void shouldParseZonedDateTime() {
+        DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault());
+        ZonedDateTime zonedDateTime = ZonedDateTime.parse("2021-10-01T05:06:20Z", formatter);
+        
+        Assert.assertEquals("2021-10-01T05:06:20Z", DateTimeFormatter.ISO_INSTANT.format(zonedDateTime));
+    }
+    
+    @Test(expected = DateTimeParseException.class)
+    public void shouldExpectAnExceptionIfTimeZoneIsMissing() {
+        ZonedDateTime zonedDateTime = ZonedDateTime.parse("2021-11-01T05:06:20Z", DateTimeFormatter.ISO_INSTANT);
+    }
+    
+    @Test(expected = DateTimeParseException.class)
+    public void shouldExpectAnExceptionIfSecondIsMissing() {
+        ZonedDateTime zonedDateTime = ZonedDateTime.parse("2021-12-02T08:06Z", DateTimeFormatter.ISO_INSTANT);
+    }
 }
diff --git a/core-java-modules/core-java-exceptions-2/pom.xml b/core-java-modules/core-java-exceptions-2/pom.xml
index af7a778b23..9103672cd4 100644
--- a/core-java-modules/core-java-exceptions-2/pom.xml
+++ b/core-java-modules/core-java-exceptions-2/pom.xml
@@ -15,24 +15,11 @@
     
 
     
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
             org.apache.commons
             commons-lang3
-            ${commons.lang3.version}
+            ${commons-lang3.version}
         
     
 
-    
-        3.10
-        
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-exceptions-3/README.md b/core-java-modules/core-java-exceptions-3/README.md
index f79eb41a8b..d269444ccb 100644
--- a/core-java-modules/core-java-exceptions-3/README.md
+++ b/core-java-modules/core-java-exceptions-3/README.md
@@ -9,3 +9,4 @@
 - [Explanation of ClassCastException in Java](https://www.baeldung.com/java-classcastexception)
 - [NoSuchFieldError in Java](https://www.baeldung.com/java-nosuchfielderror)
 - [IllegalAccessError in Java](https://www.baeldung.com/java-illegalaccesserror)
+- [Working with (Unknown Source) Stack Traces in Java](https://www.baeldung.com/java-unknown-source-stack-trace)
diff --git a/core-java-modules/core-java-exceptions-3/pom.xml b/core-java-modules/core-java-exceptions-3/pom.xml
index bdee998e8d..455f769757 100644
--- a/core-java-modules/core-java-exceptions-3/pom.xml
+++ b/core-java-modules/core-java-exceptions-3/pom.xml
@@ -19,21 +19,29 @@
         
             com.h2database
             h2
-            1.4.191
-            test
-        
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
+            ${h2.version}
             test
         
     
 
+    
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                3.8.1
+                
+                    
+
+
+                    
+                
+            
+        
+    
+
     
-        
-        3.10.0
+        1.4.191
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedReceiver.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedReceiver.java
index ff6b926cdc..8b0aa95153 100644
--- a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedReceiver.java
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedReceiver.java
@@ -4,7 +4,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class SynchronizedReceiver implements Runnable {
-    private static Logger log = LoggerFactory.getLogger(SynchronizedReceiver.class);
+
+    private static final Logger LOG = LoggerFactory.getLogger(SynchronizedReceiver.class);
+
     private final Data data;
     private String message;
     private boolean illegalMonitorStateExceptionOccurred;
@@ -20,10 +22,10 @@ public class SynchronizedReceiver implements Runnable {
                 data.wait();
                 this.message = data.receive();
             } catch (InterruptedException e) {
-                log.error("thread was interrupted", e);
+                LOG.error("thread was interrupted", e);
                 Thread.currentThread().interrupt();
             } catch (IllegalMonitorStateException e) {
-                log.error("illegal monitor state exception occurred", e);
+                LOG.error("illegal monitor state exception occurred", e);
                 illegalMonitorStateExceptionOccurred = true;
             }
         }
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedSender.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedSender.java
index 1618bc8efa..8317b5ade7 100644
--- a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedSender.java
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/SynchronizedSender.java
@@ -4,7 +4,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class SynchronizedSender implements Runnable {
-    private static Logger log = LoggerFactory.getLogger(SynchronizedSender.class);
+
+    private static final Logger LOG = LoggerFactory.getLogger(SynchronizedSender.class);
+
     private final Data data;
     private boolean illegalMonitorStateExceptionOccurred;
 
@@ -22,10 +24,10 @@ public class SynchronizedSender implements Runnable {
 
                 data.notifyAll();
             } catch (InterruptedException e) {
-                log.error("thread was interrupted", e);
+                LOG.error("thread was interrupted", e);
                 Thread.currentThread().interrupt();
             } catch (IllegalMonitorStateException e) {
-                log.error("illegal monitor state exception occurred", e);
+                LOG.error("illegal monitor state exception occurred", e);
                 illegalMonitorStateExceptionOccurred = true;
             }
         }
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedReceiver.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedReceiver.java
index 3a0b72e6cd..69fb363731 100644
--- a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedReceiver.java
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedReceiver.java
@@ -4,7 +4,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class UnsynchronizedReceiver implements Runnable {
-    private static Logger log = LoggerFactory.getLogger(UnsynchronizedReceiver.class);
+    private static final Logger LOG = LoggerFactory.getLogger(UnsynchronizedReceiver.class);
+
     private final Data data;
     private String message;
     private boolean illegalMonitorStateExceptionOccurred;
@@ -19,10 +20,10 @@ public class UnsynchronizedReceiver implements Runnable {
             data.wait();
             this.message = data.receive();
         } catch (InterruptedException e) {
-            log.error("thread was interrupted", e);
+            LOG.error("thread was interrupted", e);
             Thread.currentThread().interrupt();
         } catch (IllegalMonitorStateException e) {
-            log.error("illegal monitor state exception occurred", e);
+            LOG.error("illegal monitor state exception occurred", e);
             illegalMonitorStateExceptionOccurred = true;
         }
     }
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedSender.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedSender.java
index 7f15418bfa..b97453f655 100644
--- a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedSender.java
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalmonitorstate/UnsynchronizedSender.java
@@ -4,7 +4,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class UnsynchronizedSender implements Runnable {
-    private static Logger log = LoggerFactory.getLogger(UnsynchronizedSender.class);
+    private static final Logger LOG = LoggerFactory.getLogger(UnsynchronizedSender.class);
+
     private final Data data;
     private boolean illegalMonitorStateExceptionOccurred;
 
@@ -21,10 +22,10 @@ public class UnsynchronizedSender implements Runnable {
 
             data.notifyAll();
         } catch (InterruptedException e) {
-            log.error("thread was interrupted", e);
+            LOG.error("thread was interrupted", e);
             Thread.currentThread().interrupt();
         } catch (IllegalMonitorStateException e) {
-            log.error("illegal monitor state exception occurred", e);
+            LOG.error("illegal monitor state exception occurred", e);
             illegalMonitorStateExceptionOccurred = true;
         }
     }
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/Main.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/Main.java
new file mode 100644
index 0000000000..0806a4bf80
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/Main.java
@@ -0,0 +1,25 @@
+package com.baeldung.unknownsourcestacktrace;
+
+import com.baeldung.unknownsourcestacktrace.dto.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Main {
+    private static final Logger logger = LoggerFactory.getLogger(Main.class);
+    private static final int SHORT_NAME_LIMIT = 10;
+
+    public static void main(String[] args) {
+        User user = new User();
+        user.setName("Tom");
+
+        logger.info(getGreetingMessage(user.getName()));
+    }
+
+    private static String getGreetingMessage(String name) {
+        return "Welcome " + getShortenedName(name) + "!";
+    }
+
+    private static String getShortenedName(String name) {
+        return name.substring(0, SHORT_NAME_LIMIT);
+    }
+}
diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/dto/User.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/dto/User.java
new file mode 100644
index 0000000000..997631ea46
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/unknownsourcestacktrace/dto/User.java
@@ -0,0 +1,13 @@
+package com.baeldung.unknownsourcestacktrace.dto;
+
+public class User {
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java
index 82c00bc72f..857ab02c13 100644
--- a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java
+++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java
@@ -1,8 +1,11 @@
 package com.baeldung.exceptions.illegalmonitorstate;
 
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
 
 public class IllegalMonitorStateExceptionUnitTest {
 
@@ -18,10 +21,9 @@ public class IllegalMonitorStateExceptionUnitTest {
         Thread senderThread = new Thread(sender, "sender-thread");
         senderThread.start();
 
-        senderThread.join(1000);
-        receiverThread.join(1000);
-        
-        Thread.sleep(2000);
+        // we need to wait for the sender and receiver threads to finish
+        senderThread.join(10_000);
+        receiverThread.join(10_000);
 
         assertEquals("test", receiver.getMessage());
         assertFalse(sender.hasIllegalMonitorStateExceptionOccurred());
diff --git a/core-java-modules/core-java-exceptions-4/README.md b/core-java-modules/core-java-exceptions-4/README.md
new file mode 100644
index 0000000000..259feb685c
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Java ArrayIndexOutOfBoundsException](https://www.baeldung.com/java-arrayindexoutofboundsexception)
diff --git a/core-java-modules/core-java-exceptions-4/pom.xml b/core-java-modules/core-java-exceptions-4/pom.xml
new file mode 100644
index 0000000000..cc81fdc40b
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/pom.xml
@@ -0,0 +1,47 @@
+
+
+    4.0.0
+    com.baeldung.exceptions
+    core-java-exceptions-4
+    0.1.0-SNAPSHOT
+    core-java-exceptions-4
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        
+            com.h2database
+            h2
+            ${h2.version}
+            test
+        
+    
+
+    
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                3.8.1
+                
+                    
+
+
+                    
+                
+            
+        
+    
+
+    
+        1.4.191
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemo.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemo.java
new file mode 100644
index 0000000000..6b320976a6
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemo.java
@@ -0,0 +1,31 @@
+package com.baeldung.exception.arrayindexoutofbounds;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ArrayIndexOutOfBoundsExceptionDemo {
+
+    public static void main(String[] args) {
+        int[] numbers = new int[] { 1, 2, 3, 4, 5 };
+        
+        getArrayElementAtIndex(numbers, 5);
+        getListElementAtIndex(5);
+        addArrayElementsUsingLoop(numbers);
+    }
+
+    public static void addArrayElementsUsingLoop(int[] numbers) {
+        int sum = 0;
+        for (int i = 0; i <= numbers.length; i++) {
+            sum += numbers[i];
+        }
+    }
+
+    public static int getListElementAtIndex(int index) {
+        List numbersList = Arrays.asList(1, 2, 3, 4, 5);
+        return numbersList.get(index);
+    }
+
+    public static int getArrayElementAtIndex(int[] numbers, int index) {
+        return numbers[index];
+    }
+}
diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatement.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatement.java
new file mode 100644
index 0000000000..d76ae76a0e
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatement.java
@@ -0,0 +1,41 @@
+package com.baeldung.exception.missingreturnstatement;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class MissingReturnStatement {
+    public static void main(String[] args) {
+        int a = -12;
+        int result = pow(a);
+        System.out.println(result);
+        Map dictionary = createDictionary();
+        dictionary.forEach((s, integer) -> System.out.println(s + " " + integer));
+    }
+
+    public static int pow(int number) {
+        int pow = number * number;
+        return pow;
+    }
+
+    public static String checkNumber(int number) {
+        if (number == 0) {
+            return "It's equals to zero";
+        }
+
+        for (int i = 0; i < number; i++) {
+            if (i > 100) {
+                return "It's a big number";
+            }
+        }
+        return "It's a negative number";
+    }
+
+    public static Map createDictionary() {
+        List words = Arrays.asList("Hello", "World");
+        return words.stream()
+            .collect(Collectors.toMap(s -> s, s -> 1));
+    }
+
+}
diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemoUnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemoUnitTest.java
new file mode 100644
index 0000000000..e1ad2b8021
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/arrayindexoutofbounds/ArrayIndexOutOfBoundsExceptionDemoUnitTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.exception.arrayindexoutofbounds;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class ArrayIndexOutOfBoundsExceptionDemoUnitTest {
+
+    private static int[] numbers;
+
+    @BeforeAll
+    public static void setUp() {
+        numbers = new int[] { 1, 2, 3, 4, 5 };
+    }
+
+    @Test
+    void givenAnArrayOfSizeFive_whenAccessedElementBeyondRange_thenShouldThrowArrayIndexOutOfBoundsException() {
+        assertThrows(ArrayIndexOutOfBoundsException.class,
+          () -> ArrayIndexOutOfBoundsExceptionDemo.addArrayElementsUsingLoop(numbers));
+    }
+
+    @Test
+    void givenAnArrayOfSizeFive_whenAccessedAnElementAtIndexEqualToSize_thenShouldThrowArrayIndexOutOfBoundsException() {
+        assertThrows(ArrayIndexOutOfBoundsException.class,
+          () -> ArrayIndexOutOfBoundsExceptionDemo.getArrayElementAtIndex(numbers, 5));
+    }
+
+    @Test
+    void givenAListReturnedByArraysAsListMethod_whenAccessedAnElementAtIndexEqualToSize_thenShouldThrowArrayIndexOutOfBoundsException() {
+        assertThrows(ArrayIndexOutOfBoundsException.class,
+          () -> ArrayIndexOutOfBoundsExceptionDemo.getListElementAtIndex(5));
+    }
+}
diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatementUnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatementUnitTest.java
new file mode 100644
index 0000000000..97a050a3f0
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/missingreturnstatement/MissingReturnStatementUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.exception.missingreturnstatement;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+public class MissingReturnStatementUnitTest {
+
+    @Test
+    public void givenANumber_thenReturnItsPow() {
+        int number = 10;
+        int pow = MissingReturnStatement.pow(number);
+        assertEquals(100, pow);
+    }
+
+    @Test
+    public void givenABigNumber_thenReturnItsType() {
+        int number = 200;
+        String type = MissingReturnStatement.checkNumber(number);
+        assertEquals("It's a big number", type);
+    }
+
+    @Test
+    public void givenANegativeNumber_thenReturnItsType() {
+        int number = -10;
+        String type = MissingReturnStatement.checkNumber(number);
+        assertEquals("It's a negative number", type);
+    }
+
+    @Test
+    public void getStringDictionary_thenPrintValues() {
+        Map dictionary = MissingReturnStatement.createDictionary();
+        assertEquals(2, dictionary.size());
+        dictionary.forEach((s, integer) -> System.out.println(s + " - " + integer));
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml
index 1f15dabe36..f1f60120a5 100644
--- a/core-java-modules/core-java-exceptions/pom.xml
+++ b/core-java-modules/core-java-exceptions/pom.xml
@@ -30,22 +30,12 @@
         
             org.apache.commons
             commons-lang3
-            ${commons.lang3.version}
-        
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
+            ${commons-lang3.version}
         
     
 
     
         1.5.0-b01
-        3.10
-        
-        3.10.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-function/pom.xml b/core-java-modules/core-java-function/pom.xml
index cc44ba5a7c..a3add5a686 100644
--- a/core-java-modules/core-java-function/pom.xml
+++ b/core-java-modules/core-java-function/pom.xml
@@ -14,16 +14,6 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-    
-
     
         core-java-function
         
@@ -34,9 +24,4 @@
         
     
 
-    
-        
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-2/pom.xml b/core-java-modules/core-java-io-2/pom.xml
index 924248f4f9..b5f43d5a94 100644
--- a/core-java-modules/core-java-io-2/pom.xml
+++ b/core-java-modules/core-java-io-2/pom.xml
@@ -15,12 +15,6 @@
     
 
     
-        
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
         
             commons-io
@@ -38,13 +32,6 @@
             log4j-over-slf4j
             ${org.slf4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
         
             com.github.tomakehurst
@@ -76,7 +63,6 @@
     
 
     
-        3.6.1
         3.0.0-M1
         2.26.3
     
diff --git a/core-java-modules/core-java-io-3/README.md b/core-java-modules/core-java-io-3/README.md
index d0ac5387a8..312797cb94 100644
--- a/core-java-modules/core-java-io-3/README.md
+++ b/core-java-modules/core-java-io-3/README.md
@@ -14,4 +14,4 @@ This module contains articles about core Java input and output (IO)
 - [Find the Last Modified File in a Directory with Java](https://www.baeldung.com/java-last-modified-file)
 - [Get a Filename Without the Extension in Java](https://www.baeldung.com/java-filename-without-extension)
 - [Writing byte[] to a File in Java](https://www.baeldung.com/java-write-byte-array-file)
-- [[<-- Prev]](/core-java-modules/core-java-io-2)
+- [[<-- Prev]](/core-java-modules/core-java-io-2)[[More -->]](/core-java-modules/core-java-io-4)
diff --git a/core-java-modules/core-java-io-3/pom.xml b/core-java-modules/core-java-io-3/pom.xml
index 017b56f03f..4901133854 100644
--- a/core-java-modules/core-java-io-3/pom.xml
+++ b/core-java-modules/core-java-io-3/pom.xml
@@ -15,12 +15,6 @@
     
 
     
-        
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
         
             commons-io
@@ -38,17 +32,6 @@
             log4j-over-slf4j
             ${org.slf4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-4/README.md b/core-java-modules/core-java-io-4/README.md
index c837e2bffc..be58338fd8 100644
--- a/core-java-modules/core-java-io-4/README.md
+++ b/core-java-modules/core-java-io-4/README.md
@@ -5,4 +5,6 @@ This module contains articles about core Java input and output (IO)
 ### Relevant Articles: 
 
 - [Java File Separator vs File Path Separator](https://www.baeldung.com/java-file-vs-file-path-separator)
+- [Simulate touch Command in Java](https://www.baeldung.com/java-simulate-touch-command)
+- [SequenceInputStream Class in Java](https://www.baeldung.com/java-sequenceinputstream)
 - [[<-- Prev]](/core-java-modules/core-java-io-3)
diff --git a/core-java-modules/core-java-io-4/pom.xml b/core-java-modules/core-java-io-4/pom.xml
index 0501bb4a66..9fc00ff586 100644
--- a/core-java-modules/core-java-io-4/pom.xml
+++ b/core-java-modules/core-java-io-4/pom.xml
@@ -32,17 +32,6 @@
             log4j-over-slf4j
             ${org.slf4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-4/src/main/java/com/baeldung/iostreams/InputSequenceHandler.java b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/iostreams/InputSequenceHandler.java
new file mode 100644
index 0000000000..7b09c3cc72
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/iostreams/InputSequenceHandler.java
@@ -0,0 +1,45 @@
+package com.baeldung.iostreams;
+
+import java.io.*;
+import java.util.List;
+import java.util.Vector;
+
+public class InputSequenceHandler {
+
+    private SequenceInputStream sequenceInputStream;
+
+    public InputSequenceHandler(Vector inputStreams) {
+        sequenceInputStream = new SequenceInputStream(inputStreams.elements());
+    }
+
+    public InputSequenceHandler(String file1, String file2) throws FileNotFoundException {
+        sequenceInputStream = new SequenceInputStream(new FileInputStream(file1), new FileInputStream(file2));
+    }
+
+    public InputSequenceHandler(List fileNames) throws FileNotFoundException {
+        Vector inputStreams = new Vector<>();
+
+        for (String fileName: fileNames) {
+            inputStreams.add(new FileInputStream(fileName));
+        }
+        sequenceInputStream = new SequenceInputStream(inputStreams.elements());
+    }
+
+
+    public int read() throws IOException {
+        return sequenceInputStream.read();
+    }
+
+    public String readAsString() throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        int readByte;
+        while ((readByte = sequenceInputStream.read()) != -1) {
+            stringBuilder.append((char) readByte);
+        }
+        return stringBuilder.toString();
+    }
+
+    public void close() throws IOException {
+        sequenceInputStream.close();
+    }
+}
diff --git a/core-java-modules/core-java-io-4/src/main/java/com/baeldung/simulation/touch/command/Simulator.java b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/simulation/touch/command/Simulator.java
new file mode 100644
index 0000000000..403981e078
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/simulation/touch/command/Simulator.java
@@ -0,0 +1,49 @@
+package com.baeldung.simulation.touch.command;
+
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.attribute.FileTime;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+public class Simulator {
+
+    public static void touch(String path, String... args) throws IOException, ParseException {
+        File file = new File(path);
+        if (!file.exists()) {
+            file.createNewFile();
+            if (args.length == 0) {
+                return;
+            }
+        }
+        long timeMillis = args.length < 2 ? System.currentTimeMillis() : new SimpleDateFormat("dd-MM-yyyy hh:mm:ss").parse(args[1]).getTime();
+        if (args.length > 0) {
+            // change access time only
+            if ("a".equals(args[0])) {
+                FileTime accessFileTime = FileTime.fromMillis(timeMillis);
+                Files.setAttribute(file.toPath(), "lastAccessTime", accessFileTime);
+                return;
+            }
+            // change modification time only
+            if ("m".equals(args[0])) {
+                file.setLastModified(timeMillis);
+                return;
+            }
+        }
+        // other cases will change both
+        FileTime accessFileTime = FileTime.fromMillis(timeMillis);
+        Files.setAttribute(file.toPath(), "lastAccessTime", accessFileTime);
+        file.setLastModified(timeMillis);
+    }
+
+    public static void touchWithApacheCommons(String path) throws IOException {
+        FileUtils.touch(new File(path));
+    }
+
+    public static void main(String[] args) throws IOException, ParseException {
+        touch("test.txt");
+    }
+}
diff --git a/core-java-modules/core-java-io-4/src/test/java/com/baeldung/iostreams/InputSequenceUnitTest.java b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/iostreams/InputSequenceUnitTest.java
new file mode 100644
index 0000000000..aa2bc24b41
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/iostreams/InputSequenceUnitTest.java
@@ -0,0 +1,77 @@
+package com.baeldung.iostreams;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class InputSequenceUnitTest {
+
+    private static final String FILE1 = "iostreams/File1.txt";
+    private static final String FILE2 = "iostreams/File2.txt";
+    private static final String FILE3 = "iostreams/File3.txt";
+
+    private static final String FILE1_AND_FILE2_CONTENT = "InputSequenceUnitTest";
+    private static final String ALL_FILES_CONTENT = "InputSequenceUnitTest is Success";
+
+    @Test
+    public void givenTwoFiles_readAsString() throws URISyntaxException, IOException {
+        String file1 = Paths.get(ClassLoader.getSystemResource(FILE1).toURI()).toString();
+        String file2 = Paths.get(ClassLoader.getSystemResource(FILE2).toURI()).toString();
+        InputSequenceHandler inputSequenceHandler = new InputSequenceHandler(file1, file2);
+        String stringValue = inputSequenceHandler.readAsString();
+        inputSequenceHandler.close();
+        assertEquals(FILE1_AND_FILE2_CONTENT, stringValue);
+    }
+
+    @Test
+    public void givenFileList_readAsString() throws URISyntaxException, IOException {
+        List filesList = new ArrayList<>();
+        filesList.add(Paths.get(ClassLoader.getSystemResource(FILE1).toURI()).toString());
+        filesList.add(Paths.get(ClassLoader.getSystemResource(FILE2).toURI()).toString());
+        filesList.add(Paths.get(ClassLoader.getSystemResource(FILE3).toURI()).toString());
+        InputSequenceHandler inputSequenceHandler = new InputSequenceHandler(filesList);
+        String stringValue = inputSequenceHandler.readAsString();
+        inputSequenceHandler.close();
+        assertEquals(ALL_FILES_CONTENT, stringValue);
+    }
+
+    @Test
+    public void givenVectorOfInputStreams_readAsString() throws IOException {
+        String[] strings = {"Testing", "Leads", "to", "failure",
+                "and", "failure", "leads", "to", "understanding"};
+        Vector inputStreamVector = new Vector<>();
+        StringBuilder stringBuilder = new StringBuilder();
+        for (String string: strings) {
+            inputStreamVector.add(new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8)));
+            stringBuilder.append(string);
+        }
+        InputSequenceHandler inputSequenceHandler = new InputSequenceHandler(inputStreamVector);
+        String combinedString = inputSequenceHandler.readAsString();
+        inputSequenceHandler.close();
+        assertEquals(stringBuilder.toString(), combinedString);
+    }
+
+    @Test
+    public void givenTwoStrings_readCombinedValue() throws IOException {
+        InputStream first = new ByteArrayInputStream("One".getBytes());
+        InputStream second = new ByteArrayInputStream("Magic".getBytes());
+        SequenceInputStream sequenceInputStream = new SequenceInputStream(first, second);
+        StringBuilder stringBuilder = new StringBuilder();
+        int byteValue;
+        while ((byteValue = sequenceInputStream.read()) != -1) {
+            stringBuilder.append((char) byteValue);
+        }
+        assertEquals("OneMagic", stringBuilder.toString());
+    }
+}
diff --git a/core-java-modules/core-java-io-4/src/test/resources/iostreams/File1.txt b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File1.txt
new file mode 100644
index 0000000000..fa17a296b5
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File1.txt
@@ -0,0 +1 @@
+InputSequence
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-4/src/test/resources/iostreams/File2.txt b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File2.txt
new file mode 100644
index 0000000000..0eb8734500
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File2.txt
@@ -0,0 +1 @@
+UnitTest
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-4/src/test/resources/iostreams/File3.txt b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File3.txt
new file mode 100644
index 0000000000..2f237d7c44
--- /dev/null
+++ b/core-java-modules/core-java-io-4/src/test/resources/iostreams/File3.txt
@@ -0,0 +1 @@
+ is Success
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-apis/pom.xml b/core-java-modules/core-java-io-apis/pom.xml
index f2a574ed89..fab2bff959 100644
--- a/core-java-modules/core-java-io-apis/pom.xml
+++ b/core-java-modules/core-java-io-apis/pom.xml
@@ -32,13 +32,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -51,8 +44,4 @@
         
     
 
-    
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-conversions-2/README.md b/core-java-modules/core-java-io-conversions-2/README.md
index b2153b3669..9abb539066 100644
--- a/core-java-modules/core-java-io-conversions-2/README.md
+++ b/core-java-modules/core-java-io-conversions-2/README.md
@@ -4,6 +4,7 @@ This module contains articles about core Java input/output(IO) conversions.
 
 ### Relevant Articles:
 - [Java InputStream to String](https://www.baeldung.com/convert-input-stream-to-string)
+- [Java String to InputStream](https://www.baeldung.com/convert-string-to-input-stream)
 - [Java – Write an InputStream to a File](https://www.baeldung.com/convert-input-stream-to-a-file)
 - [Converting a BufferedReader to a JSONObject](https://www.baeldung.com/java-bufferedreader-to-jsonobject)
 - [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array)
diff --git a/core-java-modules/core-java-io-conversions-2/pom.xml b/core-java-modules/core-java-io-conversions-2/pom.xml
index dcb9d494dc..24708ad967 100644
--- a/core-java-modules/core-java-io-conversions-2/pom.xml
+++ b/core-java-modules/core-java-io-conversions-2/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/stringtoinputstream/JavaXToInputStreamUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/stringtoinputstream/JavaXToInputStreamUnitTest.java
new file mode 100644
index 0000000000..7e7c79f764
--- /dev/null
+++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/stringtoinputstream/JavaXToInputStreamUnitTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.stringtoinputstream;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.CharSource;
+
+public class JavaXToInputStreamUnitTest {
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+    // tests - String - InputStream
+
+    @Test
+    public final void givenUsingPlainJava_whenConvertingStringToInputStream_thenCorrect() throws IOException {
+        final String initialString = "text";
+        final InputStream targetStream = new ByteArrayInputStream(initialString.getBytes());
+
+        IOUtils.closeQuietly(targetStream);
+    }
+
+    @Test
+    public final void givenUsingGuava_whenConvertingStringToInputStream_thenCorrect() throws IOException {
+        final String initialString = "text";
+        final InputStream targetStream = CharSource.wrap(initialString).asByteSource(StandardCharsets.UTF_8).openStream();
+
+        IOUtils.closeQuietly(targetStream);
+    }
+
+    @Test
+    public final void givenUsingCommonsIO_whenConvertingStringToInputStream_thenCorrect() throws IOException {
+        final String initialString = "text";
+        final InputStream targetStream = IOUtils.toInputStream(initialString);
+
+        IOUtils.closeQuietly(targetStream);
+    }
+
+}
diff --git a/core-java-modules/core-java-io-conversions/README.md b/core-java-modules/core-java-io-conversions/README.md
index 52f5222040..1f12c87241 100644
--- a/core-java-modules/core-java-io-conversions/README.md
+++ b/core-java-modules/core-java-io-conversions/README.md
@@ -13,5 +13,4 @@ This module contains articles about core Java input/output(IO) conversions.
 - [Java – Write a Reader to File](https://www.baeldung.com/java-write-reader-to-file)
 - [Java – Reader to Byte Array](https://www.baeldung.com/java-convert-reader-to-byte-array)
 - [Java – Reader to InputStream](https://www.baeldung.com/java-convert-reader-to-inputstream)
-- [Java String to InputStream](https://www.baeldung.com/convert-string-to-input-stream)
 - More articles: [[next -->]](/core-java-modules/core-java-io-conversions-2)
diff --git a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/filetoinputstream/JavaXToInputStreamUnitTest.java b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/filetoinputstream/JavaXToInputStreamUnitTest.java
index c20752639f..9d061307ce 100644
--- a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/filetoinputstream/JavaXToInputStreamUnitTest.java
+++ b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/filetoinputstream/JavaXToInputStreamUnitTest.java
@@ -1,46 +1,25 @@
 package com.baeldung.filetoinputstream;
 
-import com.google.common.io.ByteSource;
-import com.google.common.io.CharSource;
-import com.google.common.io.Files;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.*;
-import java.nio.charset.StandardCharsets;
+import com.google.common.io.ByteSource;
+import com.google.common.io.Files;
 
 public class JavaXToInputStreamUnitTest {
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    // tests - String - InputStream
-
-    @Test
-    public final void givenUsingPlainJava_whenConvertingStringToInputStream_thenCorrect() throws IOException {
-        final String initialString = "text";
-        final InputStream targetStream = new ByteArrayInputStream(initialString.getBytes());
-
-        IOUtils.closeQuietly(targetStream);
-    }
-
-    @Test
-    public final void givenUsingGuava_whenConvertingStringToInputStream_thenCorrect() throws IOException {
-        final String initialString = "text";
-        final InputStream targetStream = CharSource.wrap(initialString).asByteSource(StandardCharsets.UTF_8).openStream();
-
-        IOUtils.closeQuietly(targetStream);
-    }
-
-    @Test
-    public final void givenUsingCommonsIO_whenConvertingStringToInputStream_thenCorrect() throws IOException {
-        final String initialString = "text";
-        final InputStream targetStream = IOUtils.toInputStream(initialString);
-
-        IOUtils.closeQuietly(targetStream);
-    }
-
     // byte array - InputStream
 
     @Test
diff --git a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/readertox/JavaReaderToXUnitTest.java b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/readertox/JavaReaderToXUnitTest.java
index 72813df9b1..fa3c34d479 100644
--- a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/readertox/JavaReaderToXUnitTest.java
+++ b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/readertox/JavaReaderToXUnitTest.java
@@ -1,7 +1,7 @@
 package com.baeldung.readertox;
 
 import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -17,6 +17,7 @@ import java.nio.charset.StandardCharsets;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.input.CharSequenceReader;
+import org.apache.commons.io.input.ReaderInputStream;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -181,7 +182,7 @@ public class JavaReaderToXUnitTest {
     }
 
     @Test
-    public void givenUsingCommonsIO_whenConvertingReaderIntoInputStream() throws IOException {
+    public void givenUsingCommonsIOUtils_whenConvertingReaderIntoInputStream() throws IOException {
         final Reader initialReader = new StringReader("With Commons IO");
 
         final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader));
@@ -191,7 +192,7 @@ public class JavaReaderToXUnitTest {
     }
 
     @Test
-    public void givenUsingCommonsIO_whenConvertingReaderIntoInputStream_thenCorrect() throws IOException {
+    public void givenUsingCommonsIOUtils_whenConvertingReaderIntoInputStream_thenCorrect() throws IOException {
         String initialString = "With Commons IO";
         final Reader initialReader = new StringReader(initialString);
 
@@ -204,6 +205,30 @@ public class JavaReaderToXUnitTest {
         targetStream.close();
     }
 
+    @Test
+    public void givenUsingCommonsIOReaderInputStream_whenConvertingReaderIntoInputStream() throws IOException {
+        final Reader initialReader = new StringReader("With Commons IO");
+
+        final InputStream targetStream = new ReaderInputStream(initialReader);
+
+        initialReader.close();
+        targetStream.close();
+    }
+
+    @Test
+    public void givenUsingCommonsIOReaderInputStream_whenConvertingReaderIntoInputStream_thenCorrect() throws IOException {
+        String initialString = "With Commons IO";
+        final Reader initialReader = new StringReader(initialString);
+
+        final InputStream targetStream = new ReaderInputStream(initialReader);
+
+        final String finalString = IOUtils.toString(targetStream);
+        assertThat(finalString, equalTo(initialString));
+
+        initialReader.close();
+        targetStream.close();
+    }
+
     // tests - Reader to InputStream with encoding
 
     @Test
@@ -233,7 +258,7 @@ public class JavaReaderToXUnitTest {
     }
 
     @Test
-    public void givenUsingCommonsIO_whenConvertingReaderIntoInputStreamWithEncoding() throws IOException {
+    public void givenUsingCommonsIOUtils_whenConvertingReaderIntoInputStreamWithEncoding() throws IOException {
         final Reader initialReader = new StringReader("With Commons IO");
 
         final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader), Charsets.UTF_8);
@@ -243,7 +268,7 @@ public class JavaReaderToXUnitTest {
     }
 
     @Test
-    public void givenUsingCommonsIO_whenConvertingReaderIntoInputStreamWithEncoding_thenCorrect() throws IOException {
+    public void givenUsingCommonsIOUtils_whenConvertingReaderIntoInputStreamWithEncoding_thenCorrect() throws IOException {
         String initialString = "With Commons IO";
         final Reader initialReader = new StringReader(initialString);
         final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader), Charsets.UTF_8);
@@ -255,4 +280,27 @@ public class JavaReaderToXUnitTest {
         targetStream.close();
     }
 
+    @Test
+    public void givenUsingCommonsIOReaderInputStream_whenConvertingReaderIntoInputStreamWithEncoding() throws IOException {
+        final Reader initialReader = new StringReader("With Commons IO");
+
+        final InputStream targetStream = new ReaderInputStream(initialReader, Charsets.UTF_8);
+
+        initialReader.close();
+        targetStream.close();
+    }
+
+    @Test
+    public void givenUsingCommonsIOReaderInputStream_whenConvertingReaderIntoInputStreamWithEncoding_thenCorrect() throws IOException {
+        String initialString = "With Commons IO";
+        final Reader initialReader = new StringReader(initialString);
+
+        final InputStream targetStream = new ReaderInputStream(initialReader, Charsets.UTF_8);
+
+        String finalString = IOUtils.toString(targetStream, Charsets.UTF_8);
+        assertThat(finalString, equalTo(initialString));
+
+        initialReader.close();
+        targetStream.close();
+    }
 }
diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml
index 0cf6d6767e..7de29ac23c 100644
--- a/core-java-modules/core-java-io/pom.xml
+++ b/core-java-modules/core-java-io/pom.xml
@@ -12,17 +12,9 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.hsqldb
             hsqldb
@@ -133,8 +125,6 @@
     
 
     
-        
-        3.6.1
         
         3.0.0-M1
         2.4.0
diff --git a/core-java-modules/core-java-io/src/main/resources/logback.xml b/core-java-modules/core-java-io/src/main/resources/logback.xml
index 617917dca2..c404714347 100644
--- a/core-java-modules/core-java-io/src/main/resources/logback.xml
+++ b/core-java-modules/core-java-io/src/main/resources/logback.xml
@@ -7,13 +7,8 @@
         
     
 
-    
-    
     
 
-    
-    
-
     
         
     
diff --git a/core-java-modules/core-java-jar/README.md b/core-java-modules/core-java-jar/README.md
index f83ea496ab..fe57ede08a 100644
--- a/core-java-modules/core-java-jar/README.md
+++ b/core-java-modules/core-java-jar/README.md
@@ -8,3 +8,4 @@ This module contains articles about JAR files
 - [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class)
 - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar)
 - [Get Names of Classes Inside a JAR File](https://www.baeldung.com/jar-file-get-class-names)
+  [Find All Jars Containing Given Class](https://baeldung.com/find-all-jars-containing-given-class/)
\ No newline at end of file
diff --git a/core-java-modules/core-java-jar/pom.xml b/core-java-modules/core-java-jar/pom.xml
index 3c5a1b35bf..714a370287 100644
--- a/core-java-modules/core-java-jar/pom.xml
+++ b/core-java-modules/core-java-jar/pom.xml
@@ -49,13 +49,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
             org.javamoney
             moneta
@@ -266,118 +259,13 @@
                 
             
         
-        
-        
-            buildAgentLoader
-            
-                
-                    
-                        org.apache.maven.plugins
-                        maven-jar-plugin
-                        
-                            
-                                package
-                                
-                                    jar
-                                
-                                
-                                    agentLoader
-                                    target/classes
-                                    
-                                        
-                                            true
-                                        
-                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-                                    
-
-                                    
-                                        com/baeldung/instrumentation/application/AgentLoader.class
-                                        com/baeldung/instrumentation/application/Launcher.class
-                                    
-                                
-                            
-                        
-                    
-                
-            
-        
-        
-            buildApplication
-            
-                
-                    
-                        org.apache.maven.plugins
-                        maven-jar-plugin
-                        
-                            
-                                package
-                                
-                                    jar
-                                
-                                
-                                    application
-                                    target/classes
-                                    
-                                        
-                                            true
-                                        
-                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-                                    
-
-                                    
-                                        com/baeldung/instrumentation/application/MyAtm.class
-                                        com/baeldung/instrumentation/application/MyAtmApplication.class
-                                        com/baeldung/instrumentation/application/Launcher.class
-                                    
-                                
-                            
-                        
-                    
-                
-            
-        
-        
-            buildAgent
-            
-                
-                    
-                        org.apache.maven.plugins
-                        maven-jar-plugin
-                        
-                            
-                                package
-                                
-                                    jar
-                                
-                                
-                                    agent
-                                    target/classes
-                                    
-                                        
-                                            true
-                                        
-                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-                                    
-
-                                    
-                                        com/baeldung/instrumentation/agent/AtmTransformer.class
-                                        com/baeldung/instrumentation/agent/MyInstrumentationAgent.class
-                                    
-                                
-                            
-                        
-                    
-                
-            
-        
+       
     
 
     
         
         0.4
         1.8.7
-        
-        3.10.0
         
         1.1
         3.0.0-M1
diff --git a/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/JarApp.java b/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/JarApp.java
new file mode 100644
index 0000000000..0cdcd3c89e
--- /dev/null
+++ b/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/JarApp.java
@@ -0,0 +1,18 @@
+package com.baeldung.jar;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.net.URL;
+
+public class JarApp {
+
+    public static String findObjectMapperClass() {
+        Class klass = ObjectMapper.class;
+        URL path = klass.getProtectionDomain().getCodeSource().getLocation();
+        return path.toString();
+    }
+
+    public static void main(String[] args) {
+        System.out.println(findObjectMapperClass());
+    }
+}
diff --git a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java
new file mode 100644
index 0000000000..dc8c54eb31
--- /dev/null
+++ b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java
@@ -0,0 +1,12 @@
+package com.baeldung.jar;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+public class JarAppUnitTest {
+
+    @Test
+    public void findClassTest(){
+        Assert.assertTrue(JarApp.findObjectMapperClass().endsWith("jackson-databind-2.13.0.jar"));
+    }
+}
diff --git a/core-java-modules/core-java-jndi/README.md b/core-java-modules/core-java-jndi/README.md
index d9fb324c9a..9c6f489841 100644
--- a/core-java-modules/core-java-jndi/README.md
+++ b/core-java-modules/core-java-jndi/README.md
@@ -2,3 +2,5 @@
 ### Relevant Articles:
 
 - [Java Naming and Directory Interface Overview](https://www.baeldung.com/jndi)
+- [LDAP Authentication Using Pure Java](https://www.baeldung.com/java-ldap-auth)
+- [Testing LDAP Connections With Java](https://www.baeldung.com/java-test-ldap-connections)
diff --git a/core-java-modules/core-java-jndi/pom.xml b/core-java-modules/core-java-jndi/pom.xml
index f1b374b2b5..68b7f9361f 100644
--- a/core-java-modules/core-java-jndi/pom.xml
+++ b/core-java-modules/core-java-jndi/pom.xml
@@ -15,23 +15,6 @@
     
 
     
-        
-            org.junit.jupiter
-            junit-jupiter
-            ${junit-jupiter.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-api
-            ${junit-jupiter.version}
-            test
-        
-        
-            org.junit.jupiter
-            junit-jupiter-engine
-            ${junit-jupiter.version}
-        
         
             org.springframework
             spring-core
@@ -58,6 +41,12 @@
             h2
             ${h2.version}
         
+        
+            org.apache.directory.server
+            apacheds-test-framework
+            ${apacheds.version}
+            test
+        
     
 
     
@@ -76,6 +65,7 @@
     
         5.0.9.RELEASE
         1.4.199
+        2.0.0.AM26
         1.8
         1.8
     
diff --git a/core-java-modules/core-java-jndi/src/main/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionTool.java b/core-java-modules/core-java-jndi/src/main/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionTool.java
new file mode 100644
index 0000000000..bf605cb160
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/main/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionTool.java
@@ -0,0 +1,116 @@
+package com.baeldung.jndi.ldap.connection.tool;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+
+public class LdapConnectionTool {
+    private static final boolean DEBUG_MODE = Boolean.parseBoolean(System.getProperty("debug.mode", "false"));
+    private static final String QUERY = "query";
+
+    public static void main(String[] args) throws NamingException {
+        execute();
+    }
+
+    public static void execute() throws NamingException {
+        Hashtable env = createEnvironmentFromProperties();
+
+        DirContext context = null;
+        try {
+            context = connectToServer(env);
+
+            String query = env.get(LdapConnectionTool.QUERY);
+            if (query != null) {
+                executeQuery(context, query);
+            }
+        } catch (NamingException e) {
+            showErrorMessage(e);
+        } finally {
+            close(context);
+        }
+    }
+
+    private static void close(DirContext context) throws NamingException {
+        if (context != null) {
+            try {
+                context.close();
+            } catch (NamingException e) {
+                System.out.println(e.getMessage());
+
+                if (DEBUG_MODE)
+                    throw e;
+            }
+        }
+    }
+
+    private static void showErrorMessage(NamingException e) throws NamingException {
+        System.out.println(e.getClass() + ": " + e.getMessage());
+        Throwable cause = e.getRootCause();
+        if (cause != null) {
+            System.out.println(cause.getClass() + ": " + cause.getMessage());
+        }
+
+        if (DEBUG_MODE)
+            throw e;
+    }
+
+    private static DirContext connectToServer(Hashtable env) throws NamingException {
+        String url = env.get(Context.PROVIDER_URL);
+
+        System.out.println("connecting to " + url + "...");
+        DirContext context = new InitialDirContext(env);
+        System.out.println("successfully connected to " + url);
+        return context;
+    }
+
+    private static void executeQuery(DirContext context, String query) throws NamingException {
+        Attributes attributes = context.getAttributes(query);
+        NamingEnumeration all = attributes.getAll();
+        while (all.hasMoreElements()) {
+            Attribute next = all.next();
+
+            String key = next.getID();
+            Object value = next.get();
+
+            System.out.println(key + "=" + value);
+        }
+    }
+
+    private static Hashtable createEnvironmentFromProperties() {
+        String factory = System.getProperty("factory", "com.sun.jndi.ldap.LdapCtxFactory");
+        String authType = System.getProperty("authType", "none");
+        String url = System.getProperty("url");
+        String user = System.getProperty("user");
+        String password = System.getProperty("password");
+        String query = System.getProperty(QUERY, user);
+
+        if (url == null) {
+            throw new IllegalArgumentException("please provide 'url' system property");
+        }
+
+        Hashtable env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
+        env.put("com.sun.jndi.ldap.read.timeout", "5000");
+        env.put("com.sun.jndi.ldap.connect.timeout", "5000");
+        env.put(Context.SECURITY_AUTHENTICATION, authType);
+        env.put(Context.PROVIDER_URL, url);
+        if (query != null) {
+            env.put(LdapConnectionTool.QUERY, query);
+        }
+
+        if (user != null) {
+            if (password == null) {
+                throw new IllegalArgumentException("please provide 'password' system property");
+            }
+            env.put(Context.SECURITY_PRINCIPAL, user);
+            env.put(Context.SECURITY_CREDENTIALS, password);
+        }
+        return env;
+    }
+}
diff --git a/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/auth/JndiLdapAuthManualTest.java b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/auth/JndiLdapAuthManualTest.java
new file mode 100644
index 0000000000..5a675c62c9
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/auth/JndiLdapAuthManualTest.java
@@ -0,0 +1,165 @@
+package com.baeldung.jndi.ldap.auth;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+import java.util.Hashtable;
+
+import javax.naming.AuthenticationException;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(transports = { @CreateTransport(protocol = "LDAP", address = "localhost", port = 10390)})
+@CreateDS(
+  allowAnonAccess = false, partitions = {@CreatePartition(name = "TestPartition", suffix = "dc=baeldung,dc=com")})
+@ApplyLdifFiles({"users.ldif"})
+// class marked as manual test, as it has to run independently from the other unit tests in the module
+public class JndiLdapAuthManualTest extends AbstractLdapTestUnit {
+    
+    private static void authenticateUser(Hashtable environment) throws Exception {
+        DirContext context = new InitialDirContext(environment);   
+        context.close();       
+    }
+
+    @Test
+    public void givenPreloadedLDAPUserJoe_whenAuthUserWithCorrectPW_thenAuthSucceeds() throws Exception {
+        
+        Hashtable environment = new Hashtable();
+        environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        environment.put(Context.PROVIDER_URL, "ldap://localhost:10390");
+        environment.put(Context.SECURITY_AUTHENTICATION, "simple");
+        
+        environment.put(Context.SECURITY_PRINCIPAL, "cn=Joe Simms,ou=Users,dc=baeldung,dc=com");
+        environment.put(Context.SECURITY_CREDENTIALS, "12345");
+        
+        assertThatCode(() -> authenticateUser(environment)).doesNotThrowAnyException();
+    }
+    
+    @Test
+    public void givenPreloadedLDAPUserJoe_whenAuthUserWithWrongPW_thenAuthFails() throws Exception {
+        
+        Hashtable environment = new Hashtable();
+        environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        environment.put(Context.PROVIDER_URL, "ldap://localhost:10390");
+        environment.put(Context.SECURITY_AUTHENTICATION, "simple");
+        
+        environment.put(Context.SECURITY_PRINCIPAL, "cn=Joe Simms,ou=Users,dc=baeldung,dc=com");
+        environment.put(Context.SECURITY_CREDENTIALS, "wronguserpw");
+        
+        assertThatExceptionOfType(AuthenticationException.class).isThrownBy(() -> authenticateUser(environment));
+    }
+    
+    @Test
+    public void givenPreloadedLDAPUserJoe_whenSearchAndAuthUserWithCorrectPW_thenAuthSucceeds() throws Exception {
+        
+        // first authenticate against LDAP as admin to search up DN of user : Joe Simms
+        
+        Hashtable environment = new Hashtable();
+        environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        environment.put(Context.PROVIDER_URL, "ldap://localhost:10390");
+        environment.put(Context.SECURITY_AUTHENTICATION, "simple");        
+        environment.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
+        environment.put(Context.SECURITY_CREDENTIALS, "secret");
+        
+        DirContext adminContext = new InitialDirContext(environment);
+        
+        // define the search filter to find the person with CN : Joe Simms
+        String filter = "(&(objectClass=person)(cn=Joe Simms))";
+
+        // declare the attributes we want returned for the object being searched
+        String[] attrIDs = { "cn" };
+
+        // define the search controls
+        SearchControls searchControls = new SearchControls();
+        searchControls.setReturningAttributes(attrIDs);
+        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+        
+        // search for User with filter cn=Joe Simms
+        NamingEnumeration searchResults = adminContext.search("dc=baeldung,dc=com", filter, searchControls);
+        if (searchResults.hasMore()) {
+            
+            SearchResult result = (SearchResult) searchResults.next();
+            Attributes attrs = result.getAttributes();
+            
+            String distinguishedName = result.getNameInNamespace();
+            assertThat(distinguishedName).isEqualTo("cn=Joe Simms,ou=Users,dc=baeldung,dc=com");
+            
+            String commonName = attrs.get("cn").toString();
+            assertThat(commonName).isEqualTo("cn: Joe Simms");
+            
+            // authenticate new context with DN for user Joe Simms, using correct password
+        
+            environment.put(Context.SECURITY_PRINCIPAL, distinguishedName);
+            environment.put(Context.SECURITY_CREDENTIALS, "12345");
+            
+            assertThatCode(() -> authenticateUser(environment)).doesNotThrowAnyException();
+        }
+        
+        adminContext.close();               
+    }    
+    
+    @Test
+    public void givenPreloadedLDAPUserJoe_whenSearchAndAuthUserWithWrongPW_thenAuthFails() throws Exception {
+        
+        // first authenticate against LDAP as admin to search up DN of user : Joe Simms
+        
+        Hashtable environment = new Hashtable();
+        environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        environment.put(Context.PROVIDER_URL, "ldap://localhost:10390");
+        environment.put(Context.SECURITY_AUTHENTICATION, "simple");
+        environment.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
+        environment.put(Context.SECURITY_CREDENTIALS, "secret");
+        DirContext adminContext = new InitialDirContext(environment);
+        
+        // define the search filter to find the person with CN : Joe Simms
+        String filter = "(&(objectClass=person)(cn=Joe Simms))";
+
+        // declare the attributes we want returned for the object being searched
+        String[] attrIDs = { "cn" };
+
+        // define the search controls
+        SearchControls searchControls = new SearchControls();
+        searchControls.setReturningAttributes(attrIDs);
+        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+        
+        // search for User with filter cn=Joe Simms
+        NamingEnumeration searchResults = adminContext.search("dc=baeldung,dc=com", filter, searchControls);
+        if (searchResults.hasMore()) {
+            
+            SearchResult result = (SearchResult) searchResults.next();
+            Attributes attrs = result.getAttributes();
+            
+            String distinguishedName = result.getNameInNamespace();
+            assertThat(distinguishedName).isEqualTo("cn=Joe Simms,ou=Users,dc=baeldung,dc=com");
+
+            String commonName = attrs.get("cn").toString();
+            assertThat(commonName).isEqualTo("cn: Joe Simms");
+            
+            // authenticate new context with DN for user Joe Simms, using wrong password
+        
+            environment.put(Context.SECURITY_PRINCIPAL, distinguishedName);
+            environment.put(Context.SECURITY_CREDENTIALS, "wronguserpassword");
+            
+            assertThatExceptionOfType(AuthenticationException.class).isThrownBy(() -> authenticateUser(environment));
+        }
+        
+        adminContext.close();               
+    }
+}
diff --git a/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionToolManualTest.java b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionToolManualTest.java
new file mode 100644
index 0000000000..21898ddaf7
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/ldap/connection/tool/LdapConnectionToolManualTest.java
@@ -0,0 +1,87 @@
+package com.baeldung.jndi.ldap.connection.tool;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+import javax.naming.NamingException;
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(allowAnonymousAccess = true, transports = { @CreateTransport(protocol = "LDAP", address = "localhost", port = 10389) })
+@CreateDS(allowAnonAccess = true, partitions = { @CreatePartition(name = "ldap-connection-tool", suffix = "dc=baeldung,dc=com") })
+@ApplyLdifFiles({ "ldap-connection-tool.ldif" })
+// class marked as manual test, as it has to run independently of other unit tests in the module
+public class LdapConnectionToolManualTest extends AbstractLdapTestUnit {
+    @Before
+    public void init() {
+        System.setProperty("debug.mode", "true");
+        System.clearProperty("url");
+        System.clearProperty("user");
+        System.clearProperty("password");
+        System.clearProperty("query");
+    }
+
+    @Test
+    public void whenNoUrlProvided_thenConnectionFails() throws Exception {
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> LdapConnectionTool.execute());
+    }
+
+    @Test
+    public void givenUrlProvided_whenValidUrl_thenConnectionSucceeds() throws Exception {
+        System.setProperty("url", "ldap://localhost:10389");
+
+        assertThatCode(() -> LdapConnectionTool.execute()).doesNotThrowAnyException();
+    }
+
+    @Test
+    public void givenUrlProvided_whenInvalidUrl_thenConnectionFails() throws Exception {
+        System.setProperty("url", "ldap://unkownhost:10389");
+
+        assertThatExceptionOfType(NamingException.class).isThrownBy(() -> LdapConnectionTool.execute());
+    }
+
+    @Test
+    public void givenUserProvided_whenCorrectPassword_thenConnectionSucceeds() throws Exception {
+        System.setProperty("url", "ldap://localhost:10389");
+        System.setProperty("user", "uid=gauss,dc=baeldung,dc=com");
+        System.setProperty("password", "password");
+
+        assertThatCode(() -> LdapConnectionTool.execute()).doesNotThrowAnyException();
+    }
+
+    @Test
+    public void givenUserProvided_whenPasswordIsNull_thenConnectionFails() throws Exception {
+        System.setProperty("url", "ldap://localhost:10389");
+        System.setProperty("user", "uid=gauss,dc=baeldung,dc=com");
+
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> LdapConnectionTool.execute());
+    }
+
+    @Test
+    public void whenOnlyValidQueryProvided_thenConnectionSucceeds() throws Exception {
+        System.setProperty("url", "ldap://localhost:10389");
+        System.setProperty("query", "uid=gauss,dc=baeldung,dc=com");
+
+        assertThatCode(() -> LdapConnectionTool.execute()).doesNotThrowAnyException();
+    }
+
+    @Test
+    public void givenUserProvided_whenQueryProvided_thenConnectionSucceeds() throws Exception {
+        System.setProperty("url", "ldap://localhost:10389");
+        System.setProperty("user", "uid=gauss,dc=baeldung,dc=com");
+        System.setProperty("password", "password");
+        System.setProperty("query", "uid=newton,dc=baeldung,dc=com");
+
+        assertThatCode(() -> LdapConnectionTool.execute()).doesNotThrowAnyException();
+    }
+}
diff --git a/core-java-modules/core-java-jndi/src/test/resources/ldap-connection-tool.ldif b/core-java-modules/core-java-jndi/src/test/resources/ldap-connection-tool.ldif
new file mode 100644
index 0000000000..9b68cb8a1d
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/test/resources/ldap-connection-tool.ldif
@@ -0,0 +1,34 @@
+version: 1
+dn: dc=baeldung,dc=com
+objectClass: top
+objectClass: dcObject
+objectClass: organization
+dc: baeldung
+o: baeldung.com
+
+dn: cn=admin,dc=baeldung,dc=com
+objectClass: simpleSecurityObject
+objectClass: organizationalRole
+cn: admin
+description: LDAP administrator
+userPassword: password
+
+dn: uid=newton,dc=baeldung,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Isaac Newton
+sn: Newton
+uid: newton
+userPassword: password
+
+dn: uid=gauss,dc=baeldung,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Carl Friedrich Gauss
+sn: Gauss
+uid: gauss
+userPassword: password
\ No newline at end of file
diff --git a/core-java-modules/core-java-jndi/src/test/resources/logback.xml b/core-java-modules/core-java-jndi/src/test/resources/logback.xml
new file mode 100644
index 0000000000..eaad569e43
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+            
+        
+    
+
+    
+        
+    
+
diff --git a/core-java-modules/core-java-jndi/src/test/resources/users.ldif b/core-java-modules/core-java-jndi/src/test/resources/users.ldif
new file mode 100644
index 0000000000..c1996586d5
--- /dev/null
+++ b/core-java-modules/core-java-jndi/src/test/resources/users.ldif
@@ -0,0 +1,20 @@
+version: 1
+dn: dc=baeldung,dc=com
+objectClass: domain
+objectClass: top
+dc: baeldung
+
+dn: ou=Users,dc=baeldung,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: Users
+
+dn: cn=Joe Simms,ou=Users,dc=baeldung,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Joe Simms
+sn: Simms
+uid: user1
+userPassword: 12345
diff --git a/core-java-modules/core-java-jpms/pom.xml b/core-java-modules/core-java-jpms/pom.xml
index 65f5afad47..62aa49f299 100644
--- a/core-java-modules/core-java-jpms/pom.xml
+++ b/core-java-modules/core-java-jpms/pom.xml
@@ -25,7 +25,7 @@
                 
                     org.apache.maven.plugins
                     maven-compiler-plugin
-                    ${compiler.plugin.version}
+                    ${maven-compiler-plugin.version}
                     
                         ${source.version}
                         ${target.version}
@@ -36,7 +36,6 @@
     
 
     
-        3.8.0
         11
         11
     
diff --git a/core-java-modules/core-java-jvm-2/README.md b/core-java-modules/core-java-jvm-2/README.md
index ccca3a11ac..94ebe262c8 100644
--- a/core-java-modules/core-java-jvm-2/README.md
+++ b/core-java-modules/core-java-jvm-2/README.md
@@ -12,4 +12,5 @@ This module contains articles about working with the Java Virtual Machine (JVM).
 - [Memory Address of Objects in Java](https://www.baeldung.com/java-object-memory-address)
 - [List All Classes Loaded in a Specific Class Loader](https://www.baeldung.com/java-list-classes-class-loader)
 - [An Introduction to the Constant Pool in the JVM](https://www.baeldung.com/jvm-constant-pool)
+- [List All the Classes Loaded in the JVM](https://www.baeldung.com/jvm-list-all-classes-loaded)
 - More articles: [[<-- prev]](/core-java-modules/core-java-jvm)
diff --git a/core-java-modules/core-java-jvm-2/pom.xml b/core-java-modules/core-java-jvm-2/pom.xml
index 173cf27955..01628b0908 100644
--- a/core-java-modules/core-java-jvm-2/pom.xml
+++ b/core-java-modules/core-java-jvm-2/pom.xml
@@ -15,27 +15,21 @@
     
 
     
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.openjdk.jol
             jol-core
             ${jol-core.version}
         
+        
+            org.reflections
+            reflections
+            ${reflections.version}
+        
     
 
     
-        3.6.1
         0.10
+        0.10.2
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/loadedclasslisting/ListLoadedClass.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/loadedclasslisting/ListLoadedClass.java
new file mode 100644
index 0000000000..b4a290e70d
--- /dev/null
+++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/loadedclasslisting/ListLoadedClass.java
@@ -0,0 +1,35 @@
+package com.baeldung.loadedclasslisting;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.reflections.Reflections;
+import org.reflections.scanners.SubTypesScanner;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+public class ListLoadedClass {
+
+    public ImmutableSet listClassLoaded() throws IOException {
+        return ClassPath.from(ListLoadedClass.class.getClassLoader())
+                .getAllClasses();
+    }
+
+    public Set listClassLoaded(String packageName) throws IOException {
+        return ClassPath.from(ClassLoader.getSystemClassLoader()).getAllClasses().stream()
+                .filter(clazz -> clazz.getPackageName().equals(packageName))
+                .map(ClassInfo::load)
+                .collect(Collectors.toSet());
+    }
+
+    public Set findAllClassesUsingReflectionsLibrary(String packageName) {
+        Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
+        return reflections.getSubTypesOf(Object.class)
+               .stream()
+               .collect(Collectors.toSet());
+    }
+    
+}
diff --git a/core-java-modules/core-java-jvm-2/src/test/java/com/baeldung/loadedclasslisting/ListLoadedClassUnitTest.java b/core-java-modules/core-java-jvm-2/src/test/java/com/baeldung/loadedclasslisting/ListLoadedClassUnitTest.java
new file mode 100644
index 0000000000..c3e29b27b6
--- /dev/null
+++ b/core-java-modules/core-java-jvm-2/src/test/java/com/baeldung/loadedclasslisting/ListLoadedClassUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.loadedclasslisting;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import com.baeldung.loadedclasslisting.ListLoadedClass;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+public class ListLoadedClassUnitTest {
+
+    private static final String PACKAGE_NAME = "com.baeldung.loadedclasslisting";
+
+    @Test
+    public void when_findAllClassesUsingReflectionsLibrary_thenSuccess() {
+        ListLoadedClass instance = new ListLoadedClass();
+        Set classes = instance.findAllClassesUsingReflectionsLibrary(PACKAGE_NAME);
+
+        Assertions.assertEquals(4, classes.size());
+    }
+
+    @Test
+    public void when_findAllClassesUsingGuavaLibrary_InPackage_thenSuccess() throws IOException {
+        ListLoadedClass instance = new ListLoadedClass();
+        Set classes = instance.listClassLoaded(PACKAGE_NAME);
+
+        Assertions.assertEquals(4, classes.size());
+    }
+
+    @Test
+    public void when_findAllClassesUsingGuavaLibrary_thenSuccess() throws IOException {
+        ListLoadedClass instance = new ListLoadedClass();
+        Set classes = instance.listClassLoaded();
+
+        Assertions.assertTrue(4]](/core-java-modules/core-java-jvm-2)
+
+
+To run the code for the Instrumentation: https://www.baeldung.com/java-instrumentation article:
+1- build the module
+2- run the module 3 times to build the 3 jars:
+    mvn install -PbuildAgentLoader
+    mvn install -PbuildApplication
+    mvn install -PbuildAgent
+3- update the commands in the article with the exact names of the jars generated in the target folder
+4- update the path in the AgentLoader class with the path of the agent on your system 
\ No newline at end of file
diff --git a/core-java-modules/core-java-jvm/pom.xml b/core-java-modules/core-java-jvm/pom.xml
index afbe0b0ee3..e4c0f949c2 100644
--- a/core-java-modules/core-java-jvm/pom.xml
+++ b/core-java-modules/core-java-jvm/pom.xml
@@ -12,26 +12,14 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
         
             org.apache.commons
             commons-lang3
             ${commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.javassist
             javassist
@@ -69,16 +57,128 @@
             jol-core
             ${jol-core.version}
         
+         
+            org.slf4j
+            log4j-over-slf4j
+            ${org.slf4j.version}
+        
     
 
     
-        3.6.1
-        
         3.27.0-GA
         1.8.0
         0.10
         8.0.1
         6.5.0
     
+    
+        
+        
+            buildAgentLoader
+            
+                
+                    
+                        org.apache.maven.plugins
+                        maven-jar-plugin
+                        
+                            
+                                package
+                                
+                                    jar
+                                
+                                
+                                    agentLoader
+                                    target/classes
+                                    
+                                        
+                                            true
+                                            com.baeldung.instrumentation.application.Launcher
+                                        
+                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
+                                    
+
+                                    
+                                        com/baeldung/instrumentation/application/AgentLoader.class
+                                        com/baeldung/instrumentation/application/Launcher.class
+                                    
+                                
+                            
+                        
+                    
+                
+            
+        
+        
+            buildApplication
+            
+                
+                    
+                        org.apache.maven.plugins
+                        maven-jar-plugin
+                        
+                            
+                                package
+                                
+                                    jar
+                                
+                                
+                                    application
+                                    target/classes
+                                    
+                                        
+                                            true
+                                            com.baeldung.instrumentation.application.Launcher
+                                        
+                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
+                                    
+
+                                    
+                                        com/baeldung/instrumentation/application/MyAtm.class
+                                        com/baeldung/instrumentation/application/MyAtmApplication.class
+                                        com/baeldung/instrumentation/application/Launcher.class
+                                    
+                                
+                            
+                        
+                    
+                
+            
+        
+        
+            buildAgent
+            
+                
+                    
+                        org.apache.maven.plugins
+                        maven-jar-plugin
+                        
+                            
+                                package
+                                
+                                    jar
+                                
+                                
+                                    agent
+                                    target/classes
+                                    
+                                        
+                                            true
+                                            com.baeldung.instrumentation.application.Launcher
+                                        
+                                        ${project.build.outputDirectory}/META-INF/MANIFEST.MF
+                                    
+
+                                    
+                                        com/baeldung/instrumentation/agent/AtmTransformer.class
+                                        com/baeldung/instrumentation/agent/MyInstrumentationAgent.class
+                                    
+                                
+                            
+                        
+                    
+                
+            
+        
+    
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-jvm/src/main/resources/META-INF/MANIFEST.MF b/core-java-modules/core-java-jvm/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..d16a93ec83
--- /dev/null
+++ b/core-java-modules/core-java-jvm/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Agent-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
+Can-Redefine-Classes: true
+Can-Retransform-Classes: true
+Premain-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
+Main-Class: com.baeldung.instrumentation.application.Launcher
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java
index 64532c8b6f..db710589e7 100644
--- a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java
@@ -1,15 +1,20 @@
 package com.baeldung.java8.lambda.exceptions;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.function.Consumer;
 
 public class LambdaExceptionWrappers {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(LambdaExceptionWrappers.class);
+
     public static Consumer lambdaWrapper(Consumer consumer) {
         return i -> {
             try {
                 consumer.accept(i);
             } catch (ArithmeticException e) {
-                System.err.println("Arithmetic Exception occured : " + e.getMessage());
+                LOGGER.error("Arithmetic Exception occurred.", e);
             }
         };
     }
@@ -21,7 +26,7 @@ public class LambdaExceptionWrappers {
             } catch (Exception ex) {
                 try {
                     E exCast = clazz.cast(ex);
-                    System.err.println("Exception occured : " + exCast.getMessage());
+                    LOGGER.error("Exception occurred.", exCast);
                 } catch (ClassCastException ccEx) {
                     throw ex;
                 }
@@ -46,7 +51,7 @@ public class LambdaExceptionWrappers {
             } catch (Exception ex) {
                 try {
                     E exCast = exceptionClass.cast(ex);
-                    System.err.println("Exception occured : " + exCast.getMessage());
+                    LOGGER.error("Exception occurred.", exCast);
                 } catch (ClassCastException ccEx) {
                     throw new RuntimeException(ex);
                 }
diff --git a/guest/spring-security/src/main/resources/logback.xml b/core-java-modules/core-java-lambdas/src/main/resources/logback.xml
similarity index 100%
rename from guest/spring-security/src/main/resources/logback.xml
rename to core-java-modules/core-java-lambdas/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
index 957294153b..87c01c3ded 100644
--- a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
@@ -7,14 +7,16 @@ import java.util.function.BiFunction;
 
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class MethodReferenceUnitTest {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(MethodReferenceUnitTest.class);
+
     private static  void doNothingAtAll(Object... o) {
     }
 
-    ;
-    
     @Test
     public void referenceToStaticMethod() {
         List messages = Arrays.asList("Hello", "Baeldung", "readers!");
@@ -61,7 +63,7 @@ public class MethodReferenceUnitTest {
 
     @Test
     public void limitationsAndAdditionalExamples() {
-        createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));
+        createBicyclesList().forEach(b -> LOGGER.debug("Bike brand is '{}' and frame size is '{}'", b.getBrand(), b.getFrameSize()));
         createBicyclesList().forEach((o) -> MethodReferenceUnitTest.doNothingAtAll(o));
     }
 
diff --git a/core-java-modules/core-java-lang-2/pom.xml b/core-java-modules/core-java-lang-2/pom.xml
index d1a8d68075..4a89a22577 100644
--- a/core-java-modules/core-java-lang-2/pom.xml
+++ b/core-java-modules/core-java-lang-2/pom.xml
@@ -20,11 +20,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             commons-beanutils
             commons-beanutils
@@ -45,12 +40,6 @@
             jmh-core
             ${jmh-core.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -64,9 +53,7 @@
     
 
     
-        3.12.2
         1.9.4
-        29.0-jre
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-3/pom.xml b/core-java-modules/core-java-lang-3/pom.xml
index 0eda5dd16b..331d91dff6 100644
--- a/core-java-modules/core-java-lang-3/pom.xml
+++ b/core-java-modules/core-java-lang-3/pom.xml
@@ -15,22 +15,10 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            com.google.guava
-            guava
-            ${guava.version}
-            test
-        
         
             org.apache.commons
             commons-math3
-            3.6.1
+            ${commons-math3.version}
             test
         
     
@@ -46,7 +34,7 @@
     
 
     
-        3.12.2
+        3.6.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-4/README.md b/core-java-modules/core-java-lang-4/README.md
index 4546a00fe6..e2a74b36af 100644
--- a/core-java-modules/core-java-lang-4/README.md
+++ b/core-java-modules/core-java-lang-4/README.md
@@ -9,3 +9,4 @@ This module contains articles about core features in the Java language
 - [Referencing a Method in Javadoc Comments](https://www.baeldung.com/java-method-in-javadoc)
 - [Tiered Compilation in JVM](https://www.baeldung.com/jvm-tiered-compilation)
 - [Fixing the “Declared package does not match the expected package” Error](https://www.baeldung.com/java-declared-expected-package-error)
+- [Chaining Constructors in Java](https://www.baeldung.com/java-chain-constructors)
diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Customer.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Customer.java
new file mode 100644
index 0000000000..62dbdef297
--- /dev/null
+++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Customer.java
@@ -0,0 +1,34 @@
+package com.baeldung.constructorchaining;
+
+import java.util.Objects;
+
+public class Customer extends Person {
+    private final String loyaltyCardId;
+
+    public Customer(String firstName, String lastName, int age, String loyaltyCardId) {
+        this(firstName, null, lastName, age, loyaltyCardId);
+    }
+
+    public Customer(String firstName, String middleName, String lastName, int age, String loyaltyCardId) {
+        super(firstName, middleName, lastName, age);
+        this.loyaltyCardId = loyaltyCardId;
+    }
+
+    public String getLoyaltyCardId() {
+        return loyaltyCardId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        if (!super.equals(o)) return false;
+        Customer customer = (Customer) o;
+        return Objects.equals(loyaltyCardId, customer.loyaltyCardId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), loyaltyCardId);
+    }
+}
diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Person.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Person.java
new file mode 100644
index 0000000000..02ce2220ba
--- /dev/null
+++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/constructorchaining/Person.java
@@ -0,0 +1,51 @@
+package com.baeldung.constructorchaining;
+
+import java.util.Objects;
+
+public class Person {
+    private final String firstName;
+    private final String middleName;
+    private final String lastName;
+    private final int age;
+
+    public Person(String firstName, String lastName, int age) {
+        this(firstName, null, lastName, age);
+    }
+
+
+    public Person(String firstName, String middleName, String lastName, int age) {
+        this.firstName = firstName;
+        this.middleName = middleName;
+        this.lastName = lastName;
+        this.age = age;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Person person = (Person) o;
+        return age == person.age && Objects.equals(firstName, person.firstName) && Objects.equals(middleName, person.middleName) && Objects.equals(lastName, person.lastName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(firstName, middleName, lastName, age);
+    }
+}
diff --git a/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/CustomerUnitTest.java b/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/CustomerUnitTest.java
new file mode 100644
index 0000000000..ad00ea65b8
--- /dev/null
+++ b/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/CustomerUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.constructorchaining;
+
+import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class CustomerUnitTest {
+
+    @Test
+    public void givenNameLastNameAndAge_whenUsingDedicatedConstructor_shouldInitializeFieldsAndNullifyMiddleName() {
+        Customer mark = new Customer("Mark", "Johnson", 23, "abcd1234");
+
+        assertEquals(23, mark.getAge());
+        assertEquals("Mark", mark.getFirstName());
+        assertEquals("Johnson", mark.getLastName());
+        assertEquals("abcd1234", mark.getLoyaltyCardId());
+        assertNull(mark.getMiddleName());
+    }
+
+    @Test
+    public void givenAllFieldsRequired_whenUsingDedicatedConstructor_shouldInitializeAllFields() {
+        Customer mark = new Customer("Mark", "Andrew", "Johnson", 23, "abcd1234");
+
+        assertEquals(23, mark.getAge());
+        assertEquals("Mark", mark.getFirstName());
+        assertEquals("Andrew", mark.getMiddleName());
+        assertEquals("Johnson", mark.getLastName());
+        assertEquals("abcd1234", mark.getLoyaltyCardId());
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/PersonUnitTest.java b/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/PersonUnitTest.java
new file mode 100644
index 0000000000..8322917951
--- /dev/null
+++ b/core-java-modules/core-java-lang-4/src/test/java/com/baeldung/constructorchaining/PersonUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.constructorchaining;
+
+import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class PersonUnitTest {
+
+    @Test
+    public void givenNameLastNameAndAge_whenUsingDedicatedConstructor_shouldInitializeFieldsAndNullifyMiddleName() {
+        Person mark = new Person("Mark", "Johnson", 23);
+
+        assertEquals(23, mark.getAge());
+        assertEquals("Mark", mark.getFirstName());
+        assertEquals("Johnson", mark.getLastName());
+        assertNull(mark.getMiddleName());
+    }
+
+    @Test
+    public void givenAllFieldsRequired_whenUsingDedicatedConstructor_shouldInitializeAllFields() {
+        Person mark = new Person("Mark", "Andrew", "Johnson", 23);
+
+        assertEquals(23, mark.getAge());
+        assertEquals("Mark", mark.getFirstName());
+        assertEquals("Andrew", mark.getMiddleName());
+        assertEquals("Johnson", mark.getLastName());
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-math-2/.gitignore b/core-java-modules/core-java-lang-math-2/.gitignore
index 30b2b7442c..e4c6fe9355 100644
--- a/core-java-modules/core-java-lang-math-2/.gitignore
+++ b/core-java-modules/core-java-lang-math-2/.gitignore
@@ -1,4 +1,6 @@
 /target/
 .settings/
 .classpath
-.project
\ No newline at end of file
+.project
+
+*.log
diff --git a/core-java-modules/core-java-lang-math-2/pom.xml b/core-java-modules/core-java-lang-math-2/pom.xml
index 4411d313db..e6ead53350 100644
--- a/core-java-modules/core-java-lang-math-2/pom.xml
+++ b/core-java-modules/core-java-lang-math-2/pom.xml
@@ -39,17 +39,6 @@
             colt
             ${colt.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
-        
-            org.assertj
-            assertj-core
-            ${org.assertj.core.version}
-            test
-        
         
             com.github.dpaukov
             combinatoricslib3
@@ -65,8 +54,6 @@
 
     
         3.6.1
-        3.9.0
-        27.0.1-jre
         3.3.0
         0.38
         1.0.0-beta4
diff --git a/core-java-modules/core-java-lang-math-3/pom.xml b/core-java-modules/core-java-lang-math-3/pom.xml
index b9d09dba8c..38cb6dfa17 100644
--- a/core-java-modules/core-java-lang-math-3/pom.xml
+++ b/core-java-modules/core-java-lang-math-3/pom.xml
@@ -17,13 +17,18 @@
         
             net.objecthunter
             exp4j
-            0.4.8
+            ${exp4j.version}
         
         
             com.fathzer
             javaluator
-            3.0.3
+            ${javaluator.version}
         
     
 
+    
+        0.4.8
+        3.0.3
+    
+
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-math/pom.xml b/core-java-modules/core-java-lang-math/pom.xml
index 2cc9b90fa4..37550b67d8 100644
--- a/core-java-modules/core-java-lang-math/pom.xml
+++ b/core-java-modules/core-java-lang-math/pom.xml
@@ -14,16 +14,6 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-    
-
     
         core-java-lang-math
         
@@ -34,9 +24,4 @@
         
     
 
-    
-        
-        3.6.1
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/README.md b/core-java-modules/core-java-lang-oop-constructors/README.md
index 69ade3e25a..ddd0ec6afb 100644
--- a/core-java-modules/core-java-lang-oop-constructors/README.md
+++ b/core-java-modules/core-java-lang-oop-constructors/README.md
@@ -8,3 +8,6 @@ This module contains article about constructors in Java
 - [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
 - [Private Constructors in Java](https://www.baeldung.com/java-private-constructors)
 - [Throwing Exceptions in Constructors](https://www.baeldung.com/java-constructors-exceptions)
+- [Constructors in Java Abstract Classes](https://www.baeldung.com/java-abstract-classes-constructors)
+- [Java Implicit Super Constructor is Undefined Error](https://www.baeldung.com/java-implicit-super-constructor-is-undefined-error)
+- [Constructor Specification in Java](https://www.baeldung.com/java-constructor-specification)
diff --git a/core-java-modules/core-java-lang-oop-constructors/pom.xml b/core-java-modules/core-java-lang-oop-constructors/pom.xml
index 5635059fa9..061b3c08de 100644
--- a/core-java-modules/core-java-lang-oop-constructors/pom.xml
+++ b/core-java-modules/core-java-lang-oop-constructors/pom.xml
@@ -13,17 +13,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-    
-
-    
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/AbstractClass.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/AbstractClass.java
new file mode 100644
index 0000000000..7599529014
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/AbstractClass.java
@@ -0,0 +1,5 @@
+package com.baeldung.abstractconstructors.defaultconstructor;
+
+public abstract class AbstractClass {
+    // compiler creates a default constructor
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/ConcreteClass.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/ConcreteClass.java
new file mode 100644
index 0000000000..71c418735d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/defaultconstructor/ConcreteClass.java
@@ -0,0 +1,8 @@
+package com.baeldung.abstractconstructors.defaultconstructor;
+
+public class ConcreteClass extends AbstractClass {
+
+    public ConcreteClass() {
+        super();
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/AbstractClass.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/AbstractClass.java
new file mode 100644
index 0000000000..bdd554b2d9
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/AbstractClass.java
@@ -0,0 +1,8 @@
+package com.baeldung.abstractconstructors.noargs;
+
+public abstract class AbstractClass {
+
+    public AbstractClass() {
+        System.out.println("Initializing AbstractClass");
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassA.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassA.java
new file mode 100644
index 0000000000..8339098127
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassA.java
@@ -0,0 +1,4 @@
+package com.baeldung.abstractconstructors.noargs;
+
+public class ConcreteClassA extends AbstractClass {
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassB.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassB.java
new file mode 100644
index 0000000000..cad20d2ec0
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/ConcreteClassB.java
@@ -0,0 +1,8 @@
+package com.baeldung.abstractconstructors.noargs;
+
+public class ConcreteClassB extends AbstractClass {
+
+    public ConcreteClassB() {
+        System.out.println("Initializing ConcreteClassB");
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/Counter.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/Counter.java
new file mode 100644
index 0000000000..a0471ad777
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/Counter.java
@@ -0,0 +1,18 @@
+package com.baeldung.abstractconstructors.noargs;
+
+public abstract class Counter {
+
+    int value;
+
+    private Counter() {
+        this.value = 0;
+        System.out.println("Counter No-Arguments constructor");
+    }
+
+    public Counter(int value) {
+        this.value = value;
+        System.out.println("Parametrized Counter constructor");
+    }
+
+    abstract int increment();
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/SimpleCounter.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/SimpleCounter.java
new file mode 100644
index 0000000000..93add905df
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/noargs/SimpleCounter.java
@@ -0,0 +1,13 @@
+package com.baeldung.abstractconstructors.noargs;
+
+public class SimpleCounter extends Counter {
+
+    public SimpleCounter(int value) {
+        super(value);
+    }
+
+    @Override
+    int increment() {
+        return ++value;
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/Car.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/Car.java
new file mode 100644
index 0000000000..8919636b7e
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/Car.java
@@ -0,0 +1,28 @@
+package com.baeldung.abstractconstructors.parametrized;
+
+public abstract class Car {
+
+    private int distance;
+
+    private Car(int distance) {
+        this.distance = distance;
+    }
+
+    public Car() {
+        this(0);
+        System.out.println("Car default constructor");
+    }
+
+    abstract String getInformation();
+
+    protected void display() {
+        String info = new StringBuilder(getInformation())
+          .append("\nDistance: " + getDistance())
+          .toString();
+        System.out.println(info);
+    }
+
+    public int getDistance() {
+        return distance;
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/ElectricCar.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/ElectricCar.java
new file mode 100644
index 0000000000..e17ea6d9c5
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/ElectricCar.java
@@ -0,0 +1,17 @@
+package com.baeldung.abstractconstructors.parametrized;
+
+public class ElectricCar extends Car {
+
+    int chargingTime;
+
+    public ElectricCar(int chargingTime) {
+        this.chargingTime = chargingTime;
+    }
+
+    @Override
+    String getInformation() {
+        return new StringBuilder("Electric Car")
+          .append("\nCharging Time: " + chargingTime)
+          .toString();
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/FuelCar.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/FuelCar.java
new file mode 100644
index 0000000000..c18c3a26ef
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/abstractconstructors/parametrized/FuelCar.java
@@ -0,0 +1,17 @@
+package com.baeldung.abstractconstructors.parametrized;
+
+public class FuelCar extends Car {
+
+    String fuel;
+
+    public FuelCar(String fuel) {
+        this.fuel = fuel;
+    }
+
+    @Override
+    String getInformation() {
+        return new StringBuilder("Fuel Car")
+          .append("\nFuel type: " + fuel)
+          .toString();
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Employee.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Employee.java
new file mode 100644
index 0000000000..cb90aa3253
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Employee.java
@@ -0,0 +1,24 @@
+package com.baeldung.constructorspecification.rules;
+
+class Employee extends Person {
+
+    int id;
+
+    public Employee() {
+        super();
+    }
+
+    public Employee(String name) {
+        super(name);
+    }
+
+    public Employee(int id) {
+        this();
+        //super("John"); // syntax error
+        this.id = id;
+    }
+
+    public static void main(String[] args) {
+        new Employee(100);
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Person.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Person.java
new file mode 100644
index 0000000000..9d96afdb01
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/Person.java
@@ -0,0 +1,14 @@
+package com.baeldung.constructorspecification.rules;
+
+class Person {
+
+    String name;
+
+    public Person() {
+        this("Arash");
+    }
+
+    public Person(String name) {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/RecursiveConstructorInvocation.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/RecursiveConstructorInvocation.java
new file mode 100644
index 0000000000..85ab2b6872
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/rules/RecursiveConstructorInvocation.java
@@ -0,0 +1,12 @@
+package com.baeldung.constructorspecification.rules;
+
+class RecursiveConstructorInvocation {
+
+    public RecursiveConstructorInvocation() {
+        RecursiveConstructorInvocation rci = new RecursiveConstructorInvocation();
+    }
+
+    public static void main(String[] args) {
+        new RecursiveConstructorInvocation(); // java.lang.StackOverflowError
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/simple/Person.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/simple/Person.java
new file mode 100644
index 0000000000..101df06150
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/simple/Person.java
@@ -0,0 +1,14 @@
+package com.baeldung.constructorspecification.simple;
+
+class Person {
+
+    String name;
+
+    public Person() {
+        this("Arash");   //ExplicitConstructorInvocation
+    }
+
+    public Person(String name) {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Employee.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Employee.java
new file mode 100644
index 0000000000..884fc4e404
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Employee.java
@@ -0,0 +1,15 @@
+package com.baeldung.constructorspecification.superclass;
+
+class Employee extends Person {
+
+    String name;
+
+    public Employee(int id) {
+        super(id);   //ExplicitConstructorInvocation
+    }
+
+    public Employee(int id, String name) {
+        super(id);
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Person.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Person.java
new file mode 100644
index 0000000000..24bde9f613
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/constructorspecification/superclass/Person.java
@@ -0,0 +1,10 @@
+package com.baeldung.constructorspecification.superclass;
+
+class Person {
+
+    int id;
+
+    public Person(int id) {
+        this.id = id;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Employee.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Employee.java
new file mode 100644
index 0000000000..708e2f33f8
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Employee.java
@@ -0,0 +1,26 @@
+package com.baeldung.implicitsuperconstructorundefined;
+
+public class Employee extends Person {
+
+    private Double salary;
+
+    public Employee(String name, Integer age, Double salary) {
+        // comment this super call to see the error.
+        super(name, age);
+        this.salary = salary;
+    }
+
+    public Employee(Double salary) {
+        super();
+        this.salary = salary;
+    }
+
+    public Double getSalary() {
+        return salary;
+    }
+
+    public void setSalary(Double salary) {
+        this.salary = salary;
+    }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Person.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Person.java
new file mode 100644
index 0000000000..ff4cde5db7
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/implicitsuperconstructorundefined/Person.java
@@ -0,0 +1,35 @@
+package com.baeldung.implicitsuperconstructorundefined;
+
+public class Person {
+
+    private String name;
+    
+    private Integer age;
+
+    public Person(String name, Integer age) {
+        this.name = name;
+        this.age = age;
+    }
+    
+    // comment this constructor to see the error.
+    public Person() {
+    }
+
+    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;
+    }
+
+    
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/AbstractClassUnitTest.java b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/AbstractClassUnitTest.java
new file mode 100644
index 0000000000..c72d3b0f3f
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/AbstractClassUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.abstractconstructors.noargs;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class AbstractClassUnitTest {
+
+    @Test
+    void givenNoArgsAbstractConstructor_whenNewSubclassA_thenCalled() {
+        assertNotNull(new ConcreteClassA());
+    }
+
+    @Test
+    void givenNoArgsAbstractConstructor_whenNewSubclassB_thenCalled() {
+        assertNotNull(new ConcreteClassB());
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/CounterUnitTest.java b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/CounterUnitTest.java
new file mode 100644
index 0000000000..774136c5b6
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/noargs/CounterUnitTest.java
@@ -0,0 +1,16 @@
+package com.baeldung.abstractconstructors.noargs;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class CounterUnitTest {
+
+    @Test
+    void givenNoArgAbstractConstructor_whenSubclassCreation_thenCalled() {
+        Counter counter = new SimpleCounter(1);
+        assertNotNull(counter);
+        assertEquals(1, counter.value);
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/parametrized/CarUnitTest.java b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/parametrized/CarUnitTest.java
new file mode 100644
index 0000000000..6d17861355
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-constructors/src/test/java/com/baeldung/abstractconstructors/parametrized/CarUnitTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.abstractconstructors.parametrized;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class CarUnitTest {
+    @Test
+    void givenParametrizedConstructor_whenConcreteCreation_thenCall() {
+        ElectricCar electricCar = new ElectricCar(8);
+        assertNotNull(electricCar);
+        electricCar.display();
+
+        System.out.println();
+
+        FuelCar fuelCar = new FuelCar("Gasoline");
+        assertNotNull(fuelCar);
+        fuelCar.display();
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-inheritance/pom.xml b/core-java-modules/core-java-lang-oop-inheritance/pom.xml
index e0272fb94e..4fc7e14d84 100644
--- a/core-java-modules/core-java-lang-oop-inheritance/pom.xml
+++ b/core-java-modules/core-java-lang-oop-inheritance/pom.xml
@@ -13,17 +13,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-    
-
-    
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-methods/README.md b/core-java-modules/core-java-lang-oop-methods/README.md
index 43eab24003..f34606f26a 100644
--- a/core-java-modules/core-java-lang-oop-methods/README.md
+++ b/core-java-modules/core-java-lang-oop-methods/README.md
@@ -10,3 +10,4 @@ This module contains articles about methods in Java
 - [Guide to hashCode() in Java](https://www.baeldung.com/java-hashcode)
 - [The Covariant Return Type in Java](https://www.baeldung.com/java-covariant-return-type)
 - [Does a Method’s Signature Include the Return Type in Java?](https://www.baeldung.com/java-method-signature-return-type)
+- [Solving the Hide Utility Class Public Constructor Sonar Warning](https://www.baeldung.com/java-sonar-hide-implicit-constructor)
diff --git a/core-java-modules/core-java-lang-oop-methods/pom.xml b/core-java-modules/core-java-lang-oop-methods/pom.xml
index e493f716ec..bba1365719 100644
--- a/core-java-modules/core-java-lang-oop-methods/pom.xml
+++ b/core-java-modules/core-java-lang-oop-methods/pom.xml
@@ -24,12 +24,6 @@
             commons-lang
             ${commons-lang.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
             nl.jqno.equalsverifier
             equalsverifier
@@ -39,7 +33,7 @@
     
 
     
-        1.18.12
+        1.18.22
         2.6
         3.10.0
         3.0.3
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/StringUtils.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/StringUtils.java
new file mode 100644
index 0000000000..1e94281d21
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/StringUtils.java
@@ -0,0 +1,17 @@
+package com.baeldung.utilities;
+
+public final class StringUtils {
+
+    private StringUtils() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
+
+    public static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    public static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsEnum.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsEnum.java
new file mode 100644
index 0000000000..2fa96874c0
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsEnum.java
@@ -0,0 +1,13 @@
+package com.baeldung.utilities.alternatives;
+
+public enum StringUtilsEnum {;
+
+    public static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    public static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsInterface.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsInterface.java
new file mode 100644
index 0000000000..b6afdfff5d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/alternatives/StringUtilsInterface.java
@@ -0,0 +1,13 @@
+package com.baeldung.utilities.alternatives;
+
+public interface StringUtilsInterface {
+
+    static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructor.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructor.java
new file mode 100644
index 0000000000..38e60e0216
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructor.java
@@ -0,0 +1,17 @@
+package com.baeldung.utilities.lombok;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access= AccessLevel.PRIVATE)
+public final class StringUtilsWithNoArgsConstructor {
+
+    public static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    public static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClass.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClass.java
new file mode 100644
index 0000000000..56718f8ce4
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClass.java
@@ -0,0 +1,16 @@
+package com.baeldung.utilities.lombok;
+
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class StringUtilsWithUtilityClass {
+
+    public static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    public static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/warning/StringUtilsSuppressWarning.java b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/warning/StringUtilsSuppressWarning.java
new file mode 100644
index 0000000000..d8354f993d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/main/java/com/baeldung/utilities/warning/StringUtilsSuppressWarning.java
@@ -0,0 +1,14 @@
+package com.baeldung.utilities.warning;
+
+@SuppressWarnings("java:S1118")
+public final class StringUtilsSuppressWarning {
+
+    public static boolean isEmpty(String source) {
+        return source == null || source.length() == 0;
+    }
+
+    public static String wrap(String source, String wrapWith) {
+        return isEmpty(source) ? source : wrapWith + source + wrapWith;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/StringUtilsUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/StringUtilsUnitTest.java
new file mode 100644
index 0000000000..ca8b270d8d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/StringUtilsUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.utilities;
+
+import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.*;
+
+class StringUtilsUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtils.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtils.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtils.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtils.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsEnumUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsEnumUnitTest.java
new file mode 100644
index 0000000000..4d948c44ae
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsEnumUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.utilities.alternatives;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class StringUtilsEnumUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtilsEnum.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtilsEnum.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtilsEnum.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtilsEnum.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsInterfaceUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsInterfaceUnitTest.java
new file mode 100644
index 0000000000..600f6c2156
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/alternatives/StringUtilsInterfaceUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.utilities.alternatives;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class StringUtilsInterfaceUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtilsInterface.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtilsInterface.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtilsInterface.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtilsInterface.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructorUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructorUnitTest.java
new file mode 100644
index 0000000000..b110c31080
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithNoArgsConstructorUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.utilities.lombok;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class StringUtilsWithNoArgsConstructorUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtilsWithNoArgsConstructor.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtilsWithNoArgsConstructor.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtilsWithNoArgsConstructor.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtilsWithNoArgsConstructor.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClassUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClassUnitTest.java
new file mode 100644
index 0000000000..c2f5003ada
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/lombok/StringUtilsWithUtilityClassUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.utilities.lombok;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class StringUtilsWithUtilityClassUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtilsWithUtilityClass.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtilsWithUtilityClass.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtilsWithUtilityClass.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtilsWithUtilityClass.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/warning/StringUtilsStringUtilsSuppressWarningUnitTest.java b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/warning/StringUtilsStringUtilsSuppressWarningUnitTest.java
new file mode 100644
index 0000000000..646da08cc4
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-methods/src/test/java/com/baeldung/utilities/warning/StringUtilsStringUtilsSuppressWarningUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.utilities.warning;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class StringUtilsStringUtilsSuppressWarningUnitTest {
+
+    @Test
+    void givenAnEmptyString_whenCallingIsEmpty_thenResultIsTrue() {
+        assertThat(StringUtilsSuppressWarning.isEmpty("")).isTrue();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingIsEmpty_thenResultIsFalse() {
+        assertThat(StringUtilsSuppressWarning.isEmpty("asd")).isFalse();
+    }
+
+    @Test
+    void givenAnEmptyString_whenCallingWrap_thenResultIsAnEmptyString() {
+        assertThat(StringUtilsSuppressWarning.wrap("", "wrapper")).isEmpty();
+    }
+
+    @Test
+    void givenNonEmptyString_whenCallingWrap_thenResultIsWrappedString() {
+        assertThat(StringUtilsSuppressWarning.wrap("asd", "wrapper")).isEqualTo("wrapperasdwrapper");
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-modifiers/pom.xml b/core-java-modules/core-java-lang-oop-modifiers/pom.xml
index 70c70608eb..c193073a0e 100644
--- a/core-java-modules/core-java-lang-oop-modifiers/pom.xml
+++ b/core-java-modules/core-java-lang-oop-modifiers/pom.xml
@@ -14,12 +14,6 @@
     
 
     
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
             com.h2database
             h2
@@ -29,7 +23,7 @@
     
 
     
-        3.10.0
+        1.4.197 
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-patterns/pom.xml b/core-java-modules/core-java-lang-oop-patterns/pom.xml
index 8b8b4a7b46..4b89584def 100644
--- a/core-java-modules/core-java-lang-oop-patterns/pom.xml
+++ b/core-java-modules/core-java-lang-oop-patterns/pom.xml
@@ -29,17 +29,10 @@
             gson
             ${gson.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
         2.8.2
-        3.10.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-types-2/README.md b/core-java-modules/core-java-lang-oop-types-2/README.md
index a4e7b101c3..c5e2a75f25 100644
--- a/core-java-modules/core-java-lang-oop-types-2/README.md
+++ b/core-java-modules/core-java-lang-oop-types-2/README.md
@@ -5,3 +5,4 @@ This module contains articles about types in Java
 ### Relevant Articles: 
 
 - [Convert an Array of Primitives to an Array of Objects](https://www.baeldung.com/java-primitive-array-to-object-array)
+- [Check if an Enum Value Exists in Java](https://www.baeldung.com/java-search-enum-values)
diff --git a/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Direction.java b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Direction.java
new file mode 100644
index 0000000000..935aca4d65
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Direction.java
@@ -0,0 +1,26 @@
+package com.baeldung.enums;
+
+/**
+ * Represents directions.
+ */
+public enum Direction {
+    EAST, WEST, SOUTH, NORTH;
+
+    /**
+     * Finds direction by name.
+     *
+     * @param name the name
+     * @return the direction if found else null
+     */
+    public static Direction findByName(String name) {
+        Direction result = null;
+        for (Direction direction : values()) {
+            if (direction.name().equalsIgnoreCase(name)) {
+                result = direction;
+                break;
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/EnumSearcher.java b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/EnumSearcher.java
new file mode 100644
index 0000000000..fa85cff38b
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/EnumSearcher.java
@@ -0,0 +1,19 @@
+package com.baeldung.enums;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EnumSearcher {
+    private static final Logger LOG = LoggerFactory.getLogger(EnumSearcher.class);
+
+    public static void main(String[] args) {
+        EnumSearcher enumSearcher = new EnumSearcher();
+        enumSearcher.printWeekdays();
+    }
+
+    private void printWeekdays() {
+        for (Weekday day: Weekday.values()) {
+            LOG.info("Name {}, Value {}, Stringified {}", day.name(), day.getValue(), day);
+        }
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Month.java b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Month.java
new file mode 100644
index 0000000000..f674a4be0a
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Month.java
@@ -0,0 +1,116 @@
+package com.baeldung.enums;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Represents months in a year.
+ */
+public enum Month {
+    /**
+     * January.
+     */
+    JANUARY("January", 1),
+    /**
+     * February.
+     */
+    FEBRUARY("February", 2),
+    /**
+     * March.
+     */
+    MARCH("March", 3),
+    /**
+     * April.
+     */
+    APRIL("April", 4),
+    /**
+     * May.
+     */
+    MAY("May", 5),
+    /**
+     * June.
+     */
+    JUNE("June", 6),
+    /**
+     * July.
+     */
+    JULY("July", 7),
+    /**
+     * August.
+     */
+    AUGUST("August", 8),
+    /**
+     * September.
+     */
+    SEPTEMBER("September", 9),
+    /**
+     * October.
+     */
+    OCTOBER("October", 10),
+    /**
+     * November.
+     */
+    NOVEMBER("November", 11),
+    /**
+     * December.
+     */
+    DECEMBER("December", 12),
+    ;
+
+    private final String value;
+    private final int code;
+
+    Month(String value, int code) {
+        this.value = value;
+        this.code = code;
+    }
+
+    /**
+     * Gets value.
+     *
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Gets code.
+     *
+     * @return the code
+     */
+    public int getCode() {
+        return code;
+    }
+
+    /**
+     * Find by name.
+     *
+     * @param name the name
+     * @return the month if found else Optional.empty()
+     */
+    public static Optional findByName(String name) {
+        return Arrays.stream(values()).filter(month -> month.name().equalsIgnoreCase(name)).findFirst();
+    }
+
+    /**
+     * Find by code.
+     *
+     * @param code the code
+     * @return the month if found else Optional.empty()
+     */
+    public static Optional findByCode(int code) {
+        return Arrays.stream(values()).filter(month -> month.getCode() == code).findFirst();
+    }
+
+    /**
+     * Finds month by value.
+     *
+     * @param value value
+     * @return month if value is valid
+     * @throws IllegalArgumentException if month not found for given value
+     */
+    public static Month findByValue(String value) {
+        return Arrays.stream(values()).filter(month -> month.getValue().equalsIgnoreCase(value)).findFirst().orElseThrow(IllegalArgumentException::new);
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Weekday.java b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Weekday.java
new file mode 100644
index 0000000000..3c1031cde7
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-types-2/src/main/java/com/baeldung/enums/Weekday.java
@@ -0,0 +1,85 @@
+package com.baeldung.enums;
+
+/**
+ * Represents day in a week.
+ */
+public enum Weekday {
+    /**
+     * Monday.
+     */
+    MONDAY("Monday"),
+    /**
+     * Tuesday.
+     */
+    TUESDAY("Tuesday"),
+    /**
+     * Wednesday.
+     */
+    WEDNESDAY("Wednesday"),
+    /**
+     * Thursday.
+     */
+    THURSDAY("Thursday"),
+    /**
+     * Friday.
+     */
+    FRIDAY("Friday"),
+    /**
+     * Saturday.
+     */
+    SATURDAY("Saturday"),
+    /**
+     * Sunday.
+     */
+    SUNDAY("Sunday"),
+    ;
+
+    private final String value;
+
+    Weekday(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets value.
+     *
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Find by name.
+     *
+     * @param name the name
+     * @return the weekday if found else null
+     */
+    public static Weekday findByName(String name) {
+        Weekday result = null;
+        for (Weekday day : values()) {
+            if (day.name().equalsIgnoreCase(name)) {
+                result = day;
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Find by value.
+     *
+     * @param value the value
+     * @return the weekday if found else null
+     */
+    public static Weekday findByValue(String value) {
+        Weekday result = null;
+        for (Weekday day : values()) {
+            if (day.getValue().equalsIgnoreCase(value)) {
+                result = day;
+                break;
+            }
+        }
+        return result;
+    }
+}
diff --git a/core-java-modules/core-java-lang-oop-types-2/src/test/java/com/baeldung/enums/EnumSearcherUnitTest.java b/core-java-modules/core-java-lang-oop-types-2/src/test/java/com/baeldung/enums/EnumSearcherUnitTest.java
new file mode 100644
index 0000000000..2c96837809
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-types-2/src/test/java/com/baeldung/enums/EnumSearcherUnitTest.java
@@ -0,0 +1,89 @@
+package com.baeldung.enums;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+
+public class EnumSearcherUnitTest {
+
+    @Test
+    public void givenWeekdays_whenValidDirectionNameProvided_directionIsFound() {
+        Direction result = Direction.findByName("EAST");
+        Assertions.assertThat(result).isEqualTo(Direction.EAST);
+    }
+
+    @Test
+    public void givenWeekdays_whenValidDirectionNameLowerCaseProvided_directionIsFound() {
+        Direction result = Direction.findByName("east");
+        Assertions.assertThat(result).isEqualTo(Direction.EAST);
+    }
+
+    @Test
+    public void givenWeekdays_whenInvalidDirectionNameProvided_nullIsReturned() {
+        Direction result = Direction.findByName("E");
+        Assertions.assertThat(result).isNull();
+    }
+
+    @Test
+    public void givenWeekdays_whenValidWeekdayNameProvided_weekdayIsFound() {
+        Weekday result = Weekday.findByName("MONDAY");
+        Assertions.assertThat(result).isEqualTo(Weekday.MONDAY);
+    }
+
+    @Test
+    public void givenWeekdays_whenInvalidWeekdayNameProvided_nullIsReturned() {
+        Weekday result = Weekday.findByName("MON");
+        Assertions.assertThat(result).isNull();
+    }
+
+    @Test
+    public void givenWeekdays_whenValidWeekdayValueProvided_weekdayIsFound() {
+        Weekday result = Weekday.findByValue("Monday");
+        Assertions.assertThat(result).isEqualTo(Weekday.MONDAY);
+    }
+
+    @Test
+    public void givenWeekdays_whenInvalidWeekdayValueProvided_nullIsReturned() {
+        Weekday result = Weekday.findByValue("mon");
+        Assertions.assertThat(result).isNull();
+    }
+
+    @Test
+    public void givenMonths_whenValidMonthNameProvided_optionalMonthIsReturned() {
+        Optional result = Month.findByName("JANUARY");
+        Assertions.assertThat(result).isEqualTo(Optional.of(Month.JANUARY));
+    }
+
+    @Test
+    public void givenMonths_whenInvalidMonthNameProvided_optionalEmptyIsReturned() {
+        Optional result = Month.findByName("JAN");
+        Assertions.assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void givenMonths_whenValidMonthCodeProvided_optionalMonthIsReturned() {
+        Optional result = Month.findByCode(1);
+        Assertions.assertThat(result).isEqualTo(Optional.of(Month.JANUARY));
+    }
+
+    @Test
+    public void givenMonths_whenInvalidMonthCodeProvided_optionalEmptyIsReturned() {
+        Optional result = Month.findByCode(0);
+        Assertions.assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void givenMonths_whenValidMonthValueProvided_monthIsReturned() {
+        Month result = Month.findByValue("January");
+        Assertions.assertThat(result).isEqualTo(Month.JANUARY);
+    }
+
+    @Test
+    public void givenMonths_whenInvalidMonthValueProvided_illegalArgExIsThrown() {
+        assertThatIllegalArgumentException().isThrownBy(() -> Month.findByValue("Jan"));
+    }
+}
diff --git a/core-java-modules/core-java-lang-operators-2/README.md b/core-java-modules/core-java-lang-operators-2/README.md
index bc1809a4a7..480021108d 100644
--- a/core-java-modules/core-java-lang-operators-2/README.md
+++ b/core-java-modules/core-java-lang-operators-2/README.md
@@ -6,3 +6,4 @@ This module contains articles about Java operators
 
 - [Logical vs Bitwise OR Operator](https://www.baeldung.com/java-logical-vs-bitwise-or-operator)
 - [Bitmasking in Java with Bitwise Operators](https://www.baeldung.com/java-bitmasking)
+- [Getting a Bit at a Certain Position from Integral Values](https://www.baeldung.com/java-get-bit-at-position)
diff --git a/core-java-modules/core-java-lang-operators-2/pom.xml b/core-java-modules/core-java-lang-operators-2/pom.xml
index 2b81a797e0..c36250f1ae 100644
--- a/core-java-modules/core-java-lang-operators-2/pom.xml
+++ b/core-java-modules/core-java-lang-operators-2/pom.xml
@@ -26,13 +26,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -45,9 +38,4 @@
         
     
 
-    
-        
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-operators/pom.xml b/core-java-modules/core-java-lang-operators/pom.xml
index 63f42917b8..c61fb81354 100644
--- a/core-java-modules/core-java-lang-operators/pom.xml
+++ b/core-java-modules/core-java-lang-operators/pom.xml
@@ -21,13 +21,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -40,9 +33,4 @@
         
     
 
-    
-        
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-syntax/pom.xml b/core-java-modules/core-java-lang-syntax/pom.xml
index da7d56de7b..7cdbc40fbc 100644
--- a/core-java-modules/core-java-lang-syntax/pom.xml
+++ b/core-java-modules/core-java-lang-syntax/pom.xml
@@ -26,13 +26,6 @@
             log4j-over-slf4j
             ${org.slf4j.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -45,9 +38,4 @@
         
     
 
-    
-        
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java
index a34dcd3c7e..875b1d0f6d 100644
--- a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java
+++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java
@@ -7,6 +7,6 @@ public class Building {
     private static final Logger LOGGER = LoggerFactory.getLogger(Building.class);
 
     public void paint() {
-        LOGGER.info("Painting Building");
+        LOGGER.debug("Painting Building");
     }
 }
diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java
index 88e7d2710a..c1bc6483c4 100644
--- a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java
+++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java
@@ -7,6 +7,6 @@ public class House extends Building {
     private static final Logger LOGGER = LoggerFactory.getLogger(House.class);
 
     public void paint() {
-        LOGGER.info("Painting House");
+        LOGGER.debug("Painting House");
     }
 }
diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java
index 1d9a872d69..1604f27368 100644
--- a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java
+++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java
@@ -1,8 +1,13 @@
 package com.baeldung.initializationguide;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.Serializable;
 
 public class User implements Serializable, Cloneable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(User.class);
     private static final long serialVersionUID = 1L;
     static String forum;
     private String name;
@@ -10,12 +15,12 @@ public class User implements Serializable, Cloneable {
 
     {
         id = 0;
-        System.out.println("Instance Initializer");
+        LOGGER.debug("Instance Initializer");
     }
 
     static {
-    	forum = "Java";
-        System.out.println("Static Initializer");
+        forum = "Java";
+        LOGGER.debug("Static Initializer");
     }
 
     public User(String name, int id) {
@@ -25,7 +30,7 @@ public class User implements Serializable, Cloneable {
     }
 
     public User() {
-        System.out.println("Constructor");
+        LOGGER.debug("Constructor");
     }
 
     public String getName() {
diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java
index 1b2e621b52..cdbcd9e341 100644
--- a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java
+++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java
@@ -1,12 +1,17 @@
 package com.baeldung.loops;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class LoopsInJava {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(LoopsInJava.class);
+    
     public int[] simple_for_loop() {
         int[] arr = new int[5];
         for (int i = 0; i < 5; i++) {
             arr[i] = i;
-            System.out.println("Simple for loop: i - " + i);
+            LOGGER.debug("Simple for loop: i - " + i);
         }
         return arr;
     }
@@ -16,7 +21,7 @@ public class LoopsInJava {
         int[] arr = new int[5];
         for (int num : intArr) {
             arr[num] = num;
-            System.out.println("Enhanced for-each loop: i - " + num);
+            LOGGER.debug("Enhanced for-each loop: i - " + num);
         }
         return arr;
     }
@@ -26,7 +31,7 @@ public class LoopsInJava {
         int[] arr = new int[5];
         while (i < 5) {
             arr[i] = i;
-            System.out.println("While loop: i - " + i++);
+            LOGGER.debug("While loop: i - " + i++);
         }
         return arr;
     }
@@ -36,7 +41,7 @@ public class LoopsInJava {
         int[] arr = new int[5];
         do {
             arr[i] = i;
-            System.out.println("Do-While loop: i - " + i++);
+            LOGGER.debug("Do-While loop: i - " + i++);
         } while (i < 5);
         return arr;
     }
diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
index 69e151bfcb..55b3cbfaaf 100644
--- a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
+++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
@@ -1,7 +1,13 @@
 package com.baeldung.switchstatement;
 
+import com.baeldung.loops.LoopsInJava;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class SwitchStatement {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(SwitchStatement.class);
+
     public String exampleOfIF(String animal) {
 
         String result;
@@ -42,11 +48,11 @@ public class SwitchStatement {
         switch (animal) {
 
         case "DOG":
-            System.out.println("domestic animal");
+            LOGGER.debug("domestic animal");
             result = "domestic animal";
 
         default:
-            System.out.println("unknown animal");
+            LOGGER.debug("unknown animal");
             result = "unknown animal";
 
         }
diff --git a/guest/thread-pools/src/main/resources/logback.xml b/core-java-modules/core-java-lang-syntax/src/main/resources/logback.xml
similarity index 100%
rename from guest/thread-pools/src/main/resources/logback.xml
rename to core-java-modules/core-java-lang-syntax/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/LoopsUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/LoopsUnitTest.java
index 5a8b116a2c..354a408af6 100644
--- a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/LoopsUnitTest.java
+++ b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/LoopsUnitTest.java
@@ -8,12 +8,16 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import com.baeldung.initializationguide.User;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class LoopsUnitTest {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(LoopsUnitTest.class);
     private LoopsInJava loops = new LoopsInJava();
     private static List list = new ArrayList<>();
     private static Set set = new HashSet<>();
@@ -65,41 +69,44 @@ public class LoopsUnitTest {
     @Test
     public void whenUsingSimpleFor_shouldIterateList() {
         for (int i = 0; i < list.size(); i++) {
-            System.out.println(list.get(i));
+            LOGGER.debug(list.get(i));
         }
     }
 
     @Test
     public void whenUsingEnhancedFor_shouldIterateList() {
         for (String item : list) {
-            System.out.println(item);
+            LOGGER.debug(item);
         }
     }
 
     @Test
     public void whenUsingEnhancedFor_shouldIterateSet() {
         for (String item : set) {
-            System.out.println(item);
+            LOGGER.debug(item);
         }
     }
 
     @Test
     public void whenUsingEnhancedFor_shouldIterateMap() {
         for (Entry entry : map.entrySet()) {
-            System.out.println("Key: " + entry.getKey() + " - " + "Value: " + entry.getValue());
+            LOGGER.debug("Key: " + entry.getKey() + " - " + "Value: " + entry.getValue());
         }
     }
 
     @Test
     public void whenUsingSimpleFor_shouldRunLabelledLoop() {
-        aa: for (int i = 1; i <= 3; i++) {
-            if (i == 1)
+        aa:
+        for (int i = 1; i <= 3; i++) {
+            if (i == 1) {
                 continue;
-            bb: for (int j = 1; j <= 3; j++) {
+            }
+            bb:
+            for (int j = 1; j <= 3; j++) {
                 if (i == 2 && j == 2) {
                     break aa;
                 }
-                System.out.println(i + " " + j);
+                LOGGER.debug(i + " " + j);
             }
         }
     }
diff --git a/core-java-modules/core-java-networking-2/pom.xml b/core-java-modules/core-java-networking-2/pom.xml
index 0035b9c0b7..77f23be97c 100644
--- a/core-java-modules/core-java-networking-2/pom.xml
+++ b/core-java-modules/core-java-networking-2/pom.xml
@@ -37,7 +37,7 @@
         
             com.icegreen
             greenmail
-            1.5.8
+            ${greenmail.version}
             test
         
     
@@ -50,6 +50,7 @@
         4.5.9
         1.5.0-b01
         2.4.5
+        1.5.8
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/EmailService.java b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/EmailService.java
index bd2024fdfa..3d1e25e7a4 100644
--- a/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/EmailService.java
+++ b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/EmailService.java
@@ -1,40 +1,55 @@
 package com.baeldung.mail;
 
-import javax.mail.*;
+import javax.mail.Authenticator;
+import javax.mail.Message;
+import javax.mail.Multipart;
+import javax.mail.PasswordAuthentication;
+import javax.mail.Session;
+import javax.mail.Transport;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
 import java.io.File;
+import java.net.URI;
 import java.util.Properties;
 
 public class EmailService {
 
-    private String host = "";
-    private int port = 0;
-    private String username = "";
-    private String password = "";
+    private String username;
+    private String password;
 
+    private final Properties prop;
 
     public EmailService(String host, int port, String username, String password) {
-
-        this.host = host;
-        this.port = port;
-        this.username = username;
-        this.password = password;
-
-        sendMail();
-    }
-
-    private void sendMail() {
-
-        Properties prop = new Properties();
+        prop = new Properties();
         prop.put("mail.smtp.auth", true);
         prop.put("mail.smtp.starttls.enable", "true");
         prop.put("mail.smtp.host", host);
         prop.put("mail.smtp.port", port);
         prop.put("mail.smtp.ssl.trust", host);
 
+        this.username = username;
+        this.password = password;
+    }
+
+    public EmailService(String host, int port) {
+        prop = new Properties();
+        prop.put("mail.smtp.host", host);
+        prop.put("mail.smtp.port", port);
+    }
+
+    public static void main(String... args) {
+        try {
+            new EmailService("smtp.mailtrap.io", 25, "87ba3d9555fae8", "91cb4379af43ed")
+              .sendMail();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void sendMail() throws Exception {
+
         Session session = Session.getInstance(prop, new Authenticator() {
             @Override
             protected PasswordAuthentication getPasswordAuthentication() {
@@ -42,36 +57,35 @@ public class EmailService {
             }
         });
 
-        try {
+        Message message = new MimeMessage(session);
+        message.setFrom(new InternetAddress("from@gmail.com"));
+        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@gmail.com"));
+        message.setSubject("Mail Subject");
 
-                Message message = new MimeMessage(session);
-                message.setFrom(new InternetAddress("from@gmail.com"));
-                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@gmail.com"));
-                message.setSubject("Mail Subject");
+        String msg = "This is my first email using JavaMailer";
 
-                String msg = "This is my first email using JavaMailer";
+        MimeBodyPart mimeBodyPart = new MimeBodyPart();
+        mimeBodyPart.setContent(msg, "text/html; charset=utf-8");
 
-                MimeBodyPart mimeBodyPart = new MimeBodyPart();
-                mimeBodyPart.setContent(msg, "text/html");
+        MimeBodyPart attachmentBodyPart = new MimeBodyPart();
 
-                MimeBodyPart attachmentBodyPart = new MimeBodyPart();
-                attachmentBodyPart.attachFile(new File("pom.xml"));
+        attachmentBodyPart.attachFile(getFile());
 
-                Multipart multipart = new MimeMultipart();
-                multipart.addBodyPart(mimeBodyPart);
-                multipart.addBodyPart(attachmentBodyPart);
+        Multipart multipart = new MimeMultipart();
+        multipart.addBodyPart(mimeBodyPart);
+        multipart.addBodyPart(attachmentBodyPart);
 
-                message.setContent(multipart);
+        message.setContent(multipart);
 
-                Transport.send(message);
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        Transport.send(message);
     }
 
-    public static void main(String ... args) {
-        new EmailService("smtp.mailtrap.io", 25, "87ba3d9555fae8", "91cb4379af43ed");
+    private File getFile() throws Exception {
+        URI uri = this.getClass()
+          .getClassLoader()
+          .getResource("attachment.txt")
+          .toURI();
+        return new File(uri);
     }
 
 }
diff --git a/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentService.java b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentService.java
index 7d4dc57f10..fbe8a54bbe 100644
--- a/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentService.java
+++ b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentService.java
@@ -1,8 +1,5 @@
 package com.baeldung.mail.mailwithattachment;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Properties;
 import javax.mail.BodyPart;
 import javax.mail.Message;
 import javax.mail.MessagingException;
@@ -10,23 +7,23 @@ import javax.mail.Multipart;
 import javax.mail.PasswordAuthentication;
 import javax.mail.Session;
 import javax.mail.Transport;
-import javax.mail.internet.AddressException;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Properties;
 
 public class MailWithAttachmentService {
 
-    private String username = "";
-    private String password = "";
-    private String host = "";
-    private String port = "";
+    private final String username;
+    private final String password;
+    private final String host;
+    private final int port;
 
-    MailWithAttachmentService() {
-    }
-
-    MailWithAttachmentService(String username, String password, String host, String port) {
+    MailWithAttachmentService(String username, String password, String host, int port) {
         this.username = username;
         this.password = password;
         this.host = host;
@@ -40,15 +37,14 @@ public class MailWithAttachmentService {
         props.put("mail.smtp.host", this.host);
         props.put("mail.smtp.port", this.port);
 
-        Session session = Session.getInstance(props, new javax.mail.Authenticator() {
+        return Session.getInstance(props, new javax.mail.Authenticator() {
             protected PasswordAuthentication getPasswordAuthentication() {
                 return new PasswordAuthentication(username, password);
             }
         });
-        return session;
     }
 
-    public Message createMail(Session session) throws AddressException, MessagingException, IOException {
+    public void sendMail(Session session) throws MessagingException, IOException {
         Message message = new MimeMessage(session);
         message.setFrom(new InternetAddress("mail@gmail.com"));
         message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("mail@gmail.com"));
@@ -61,23 +57,27 @@ public class MailWithAttachmentService {
         multipart.addBodyPart(messageBodyPart);
 
         MimeBodyPart attachmentPart = new MimeBodyPart();
-        MimeBodyPart attachmentPart2 = new MimeBodyPart();
-
-        attachmentPart.attachFile(new File("C:\\Document1.txt"));
-        attachmentPart2.attachFile(new File("C:\\Document2.txt"));
-
+        attachmentPart.attachFile(getFile("attachment.txt"));
         multipart.addBodyPart(attachmentPart);
+
+        MimeBodyPart attachmentPart2 = new MimeBodyPart();
+        attachmentPart2.attachFile(getFile("attachment2.txt"));
         multipart.addBodyPart(attachmentPart2);
 
         message.setContent(multipart);
-
-        return message;
-    }
-
-    public void sendMail(Session session) throws MessagingException, IOException {
-
-        Message message = createMail(session);
         Transport.send(message);
     }
 
-}
\ No newline at end of file
+    private File getFile(String filename) {
+        try {
+            URI uri = this.getClass()
+              .getClassLoader()
+              .getResource(filename)
+              .toURI();
+            return new File(uri);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Unable to find file from resources: " + filename);
+        }
+    }
+
+}
diff --git a/core-java-modules/core-java-networking-2/src/main/resources/attachment.txt b/core-java-modules/core-java-networking-2/src/main/resources/attachment.txt
new file mode 100644
index 0000000000..a726ded018
--- /dev/null
+++ b/core-java-modules/core-java-networking-2/src/main/resources/attachment.txt
@@ -0,0 +1 @@
+sample attachment content
\ No newline at end of file
diff --git a/core-java-modules/core-java-networking-2/src/main/resources/attachment2.txt b/core-java-modules/core-java-networking-2/src/main/resources/attachment2.txt
new file mode 100644
index 0000000000..14c8ea9ff9
--- /dev/null
+++ b/core-java-modules/core-java-networking-2/src/main/resources/attachment2.txt
@@ -0,0 +1 @@
+sample attachment content 2
\ No newline at end of file
diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/EmailServiceLiveTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/EmailServiceLiveTest.java
new file mode 100644
index 0000000000..7f543bc612
--- /dev/null
+++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/EmailServiceLiveTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.mail;
+
+import com.icegreen.greenmail.junit.GreenMailRule;
+import com.icegreen.greenmail.util.ServerSetupTest;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+public class EmailServiceLiveTest {
+
+    @Rule
+    public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP);
+
+    private EmailService emailService;
+
+    @Before
+    public void setup() {
+        emailService = new EmailService("localhost", greenMail.getSmtp().getPort());
+    }
+
+    @Test
+    public void givenEmailMessageWithAttachment_whenEmailIsSent_MessageIsReceived() throws Exception {
+
+        emailService.sendMail();
+
+        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
+        assertEquals(1, receivedMessages.length);
+
+        MimeMessage receivedMessage = receivedMessages[0];
+        assertEquals("Mail Subject", subjectFromMessage(receivedMessage));
+        assertEquals("This is my first email using JavaMailer", emailTextFrom(receivedMessage));
+        assertEquals("sample attachment content", attachmentContentsFrom(receivedMessage));
+    }
+
+    private static String subjectFromMessage(MimeMessage receivedMessage) throws MessagingException {
+        return receivedMessage.getSubject();
+    }
+
+    private static String emailTextFrom(MimeMessage receivedMessage) throws IOException, MessagingException {
+        return ((MimeMultipart) receivedMessage.getContent())
+          .getBodyPart(0)
+          .getContent()
+          .toString();
+    }
+
+    private static String attachmentContentsFrom(MimeMessage receivedMessage) throws Exception {
+        return ((MimeMultipart) receivedMessage.getContent())
+          .getBodyPart(1)
+          .getContent()
+          .toString();
+    }
+
+}
diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentServiceLiveTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentServiceLiveTest.java
index ef82657ab5..04ad47875f 100644
--- a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentServiceLiveTest.java
+++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/mail/mailwithattachment/MailWithAttachmentServiceLiveTest.java
@@ -1,48 +1,77 @@
 package com.baeldung.mail.mailwithattachment;
 
-import static org.junit.Assert.*;
-import javax.annotation.Resource;
-import javax.mail.Session;
-
-import org.junit.After;
+import com.icegreen.greenmail.configuration.GreenMailConfiguration;
+import com.icegreen.greenmail.junit.GreenMailRule;
+import com.icegreen.greenmail.util.GreenMailUtil;
+import com.icegreen.greenmail.util.ServerSetupTest;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
-import com.baeldung.mail.mailwithattachment.MailWithAttachmentService;
-import com.icegreen.greenmail.util.GreenMail;
-import com.icegreen.greenmail.util.ServerSetupTest;
+import javax.annotation.Resource;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import static org.junit.Assert.assertEquals;
 
 public class MailWithAttachmentServiceLiveTest {
 
+    private static final String USERNAME = "testUser";
+    private static final String PASSWORD = "password";
+    private static final String HOSTNAME = "localhost";
+
+    @Rule
+    public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP)
+      .withConfiguration(
+        GreenMailConfiguration.aConfig()
+          .withUser(USERNAME, PASSWORD)
+      );
+
     @Resource
     private MailWithAttachmentService emailService;
-    private GreenMail greenMail;
 
     @Before
-    public void startMailServer() {
-        emailService = new MailWithAttachmentService();
-        greenMail = new GreenMail(ServerSetupTest.SMTP);
-        greenMail.start();
-    }
-
-    @After
-    public void stopMailServer() {
-        greenMail.stop();
-        emailService = null;
+    public void setup() {
+        emailService = new MailWithAttachmentService(
+          USERNAME, PASSWORD, HOSTNAME, greenMail.getSmtp().getPort()
+        );
     }
 
     @Test
-    public void canSendMail() {
-        try {
-            Session testSession = greenMail.getSmtp()
-                .createSession();
-            emailService.sendMail(testSession);
-            assertEquals(1, greenMail.getReceivedMessages().length);
-            
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+    public void givenEmailService_whenMessageSentWithAttachments_thenMessageIsReceived() throws Exception {
 
+        Session tlsSession = emailService.getSession();
+        emailService.sendMail(tlsSession);
+
+        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
+        assertEquals(1, receivedMessages.length);
+
+        MimeMessage receivedMessage = receivedMessages[0];
+        assertEquals("Testing Subject", subjectFrom(receivedMessage));
+        assertEquals("This is message body", emailTextFrom(receivedMessage));
+        assertEquals("sample attachment content", attachment1ContentsFrom(receivedMessage));
+        assertEquals("sample attachment content 2", attachment2ContentsFrom(receivedMessage));
+    }
+
+    private static String subjectFrom(MimeMessage receivedMessage) throws MessagingException {
+        return receivedMessage.getSubject();
+    }
+
+    private static String emailTextFrom(MimeMessage receivedMessage) throws Exception {
+        return GreenMailUtil.getBody(((MimeMultipart) receivedMessage.getContent())
+          .getBodyPart(0));
+    }
+
+    private static String attachment1ContentsFrom(MimeMessage receivedMessage) throws Exception {
+        return GreenMailUtil.getBody(((MimeMultipart) receivedMessage.getContent())
+          .getBodyPart(1));
+    }
+
+    private static String attachment2ContentsFrom(MimeMessage receivedMessage) throws Exception {
+        return GreenMailUtil.getBody(((MimeMultipart) receivedMessage.getContent())
+          .getBodyPart(2));
     }
 
 }
diff --git a/core-java-modules/core-java-networking-3/README.md b/core-java-modules/core-java-networking-3/README.md
index 0dc9ad9f70..82e75820ba 100644
--- a/core-java-modules/core-java-networking-3/README.md
+++ b/core-java-modules/core-java-networking-3/README.md
@@ -9,4 +9,5 @@ This module contains articles about networking in Java
 - [Connection Timeout vs. Read Timeout for Java Sockets](https://www.baeldung.com/java-socket-connection-read-timeout)
 - [Find Whether an IP Address Is in the Specified Range or Not in Java](https://www.baeldung.com/java-check-ip-address-range)
 - [Find the IP Address of a Client Connected to a Server](https://www.baeldung.com/java-client-get-ip-address)
+- [Unix Domain Socket in Java 16](https://www.baeldung.com/java-unix-domain-socket)
 - [[<-- Prev]](/core-java-modules/core-java-networking-2)
diff --git a/core-java-modules/core-java-networking-3/pom.xml b/core-java-modules/core-java-networking-3/pom.xml
index 4a05af8b25..297d665544 100644
--- a/core-java-modules/core-java-networking-3/pom.xml
+++ b/core-java-modules/core-java-networking-3/pom.xml
@@ -29,21 +29,10 @@
             tomcat-embed-core
             ${tomcat.embeded.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
         
             com.sun.mail
             javax.mail
-            1.6.2
+            ${javax.mail.version}
         
         
         
@@ -75,16 +64,26 @@
                 
             
         
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                
+                    16
+                    16
+                
+            
+        
     
 
     
         5.2.8.RELEASE
         9.4.31.v20200723
         10.0.0-M7
-        3.11.1
         5.3.3
         1.32
         0.17
+        1.6.2
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketClient.java b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketClient.java
new file mode 100644
index 0000000000..2a8ae05628
--- /dev/null
+++ b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketClient.java
@@ -0,0 +1,49 @@
+package com.baeldung.socket;
+
+import java.io.IOException;
+import java.net.StandardProtocolFamily;
+import java.net.UnixDomainSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.nio.file.Path;
+
+class UnixDomainSocketClient {
+
+    public static void main(String[] args) throws Exception {
+        new UnixDomainSocketClient().runClient();
+    }
+
+    void runClient() throws IOException {
+        Path socketPath = Path.of(System.getProperty("user.home"))
+          .resolve("baeldung.socket");
+        UnixDomainSocketAddress socketAddress = getAddress(socketPath);
+
+        SocketChannel channel = openSocketChannel(socketAddress);
+
+        String message = "Hello from Baeldung Unix domain socket article";
+        writeMessage(channel, message);
+    }
+
+    UnixDomainSocketAddress getAddress(Path socketPath) {
+        return UnixDomainSocketAddress.of(socketPath);
+    }
+
+    SocketChannel openSocketChannel(UnixDomainSocketAddress socketAddress) throws IOException {
+        SocketChannel channel = SocketChannel
+          .open(StandardProtocolFamily.UNIX);
+        channel.connect(socketAddress);
+        return channel;
+    }
+
+    void writeMessage(SocketChannel socketChannel, String message) throws IOException {
+        ByteBuffer buffer = ByteBuffer.allocate(1024);
+        buffer.clear();
+        buffer.put(message.getBytes());
+        buffer.flip();
+
+        while (buffer.hasRemaining()) {
+            socketChannel.write(buffer);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketServer.java b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketServer.java
new file mode 100644
index 0000000000..c3093ae00c
--- /dev/null
+++ b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/socket/UnixDomainSocketServer.java
@@ -0,0 +1,57 @@
+package com.baeldung.socket;
+
+import java.io.IOException;
+import java.net.StandardProtocolFamily;
+import java.net.UnixDomainSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+class UnixDomainSocketServer {
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        new UnixDomainSocketServer().runServer();
+    }
+
+    void runServer() throws IOException, InterruptedException {
+        Path socketPath = Path.of(System.getProperty("user.home"))
+          .resolve("baeldung.socket");
+        Files.deleteIfExists(socketPath);
+        UnixDomainSocketAddress socketAddress = getAddress(socketPath);
+
+        ServerSocketChannel serverChannel = createServerSocketChannel(socketAddress);
+
+        SocketChannel channel = serverChannel.accept();
+
+        while (true) {
+            readSocketMessage(channel)
+              .ifPresent(message -> System.out.printf("[Client message] %s%n", message));
+            Thread.sleep(100);
+        }
+    }
+
+    UnixDomainSocketAddress getAddress(Path socketPath) {
+        return UnixDomainSocketAddress.of(socketPath);
+    }
+
+    ServerSocketChannel createServerSocketChannel(UnixDomainSocketAddress socketAddress) throws IOException {
+        ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
+        serverChannel.bind(socketAddress);
+        return serverChannel;
+    }
+
+    Optional readSocketMessage(SocketChannel channel) throws IOException {
+        ByteBuffer buffer = ByteBuffer.allocate(1024);
+        int bytesRead = channel.read(buffer);
+        if (bytesRead < 0) return Optional.empty();
+        byte[] bytes = new byte[bytesRead];
+        buffer.flip();
+        buffer.get(bytes);
+        String message = new String(bytes);
+        return Optional.of(message);
+    }
+
+}
\ No newline at end of file
diff --git a/guest/tomcat-app/src/main/resources/logback.xml b/core-java-modules/core-java-networking-3/src/main/resources/logback.xml
similarity index 100%
rename from guest/tomcat-app/src/main/resources/logback.xml
rename to core-java-modules/core-java-networking-3/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java
index 95530ef292..4dfc114438 100644
--- a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java
+++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java
@@ -4,36 +4,26 @@ import org.apache.catalina.LifecycleException;
 import org.apache.catalina.startup.Tomcat;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.springframework.util.SocketUtils;
 
 import java.io.IOException;
 import java.net.ServerSocket;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
 
 public class FindFreePortUnitTest {
 
-    private static int FREE_PORT_NUMBER;
-    private static int[] FREE_PORT_RANGE;
-
-    @BeforeAll
-    public static void getExplicitFreePortNumberAndRange() {
-        try (ServerSocket serverSocket = new ServerSocket(0)) {
-            FREE_PORT_NUMBER = serverSocket.getLocalPort();
-            FREE_PORT_RANGE = new int[] {FREE_PORT_NUMBER, FREE_PORT_NUMBER + 1, FREE_PORT_NUMBER + 2};
-        } catch (IOException e) {
-            fail("No free port is available");
-        }
-    }
+    private static final int DEFAULT_RANDOM_PORT = 34307;
 
     @Test
     public void givenExplicitFreePort_whenCreatingServerSocket_thenThatPortIsAssigned() {
-        try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
+        int freePort = getFreePort();
+
+        try (ServerSocket serverSocket = new ServerSocket(freePort)) {
             assertThat(serverSocket).isNotNull();
-            assertThat(serverSocket.getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
+            assertThat(serverSocket.getLocalPort()).isEqualTo(freePort);
         } catch (IOException e) {
             fail("Port is not available");
         }
@@ -41,8 +31,10 @@ public class FindFreePortUnitTest {
 
     @Test
     public void givenExplicitOccupiedPort_whenCreatingServerSocket_thenExceptionIsThrown() {
-        try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
-            new ServerSocket(FREE_PORT_NUMBER);
+        int freePort = getFreePort();
+
+        try (ServerSocket serverSocket = new ServerSocket(freePort)) {
+            new ServerSocket(freePort);
             fail("Same port cannot be used twice");
         } catch (IOException e) {
             assertThat(e).hasMessageContaining("Address already in use");
@@ -51,7 +43,7 @@ public class FindFreePortUnitTest {
 
     @Test
     public void givenExplicitPortRange_whenCreatingServerSocket_thenOnePortIsAssigned() {
-        for (int port : FREE_PORT_RANGE) {
+        for (int port : getFreePorts()) {
             try (ServerSocket serverSocket = new ServerSocket(port)) {
                 assertThat(serverSocket).isNotNull();
                 assertThat(serverSocket.getLocalPort()).isEqualTo(port);
@@ -104,11 +96,12 @@ public class FindFreePortUnitTest {
     public void givenExplicitFreePort_whenCreatingJettyServer_thenThatPortIsAssigned() throws Exception {
         Server jettyServer = new Server();
         ServerConnector serverConnector = new ServerConnector(jettyServer);
-        serverConnector.setPort(FREE_PORT_NUMBER);
+        int freePort = getFreePort();
+        serverConnector.setPort(freePort);
         jettyServer.addConnector(serverConnector);
         try {
             jettyServer.start();
-            assertThat(serverConnector.getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
+            assertThat(serverConnector.getLocalPort()).isEqualTo(freePort);
         } catch (Exception e) {
             fail("Failed to start Jetty server");
         } finally {
@@ -135,10 +128,11 @@ public class FindFreePortUnitTest {
     @Test
     public void givenExplicitFreePort_whenCreatingTomcatServer_thenThatPortIsAssigned() throws Exception {
         Tomcat tomcatServer = new Tomcat();
-        tomcatServer.setPort(FREE_PORT_NUMBER);
+        int freePort = getFreePort();
+        tomcatServer.setPort(freePort);
         try {
             tomcatServer.start();
-            assertThat(tomcatServer.getConnector().getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
+            assertThat(tomcatServer.getConnector().getLocalPort()).isEqualTo(freePort);
         } catch (LifecycleException e) {
             fail("Failed to start Tomcat server");
         } finally {
@@ -147,4 +141,16 @@ public class FindFreePortUnitTest {
         }
     }
 
+    private int[] getFreePorts() {
+        int freePort = getFreePort();
+        return new int[]{freePort - 1, freePort, freePort + 1};
+    }
+
+    private int getFreePort() {
+        try(ServerSocket serverSocket = new ServerSocket(0)){
+            return serverSocket.getLocalPort();
+        } catch (IOException ex){
+            return DEFAULT_RANDOM_PORT;
+        }
+    }
 }
diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketClientUnitTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketClientUnitTest.java
new file mode 100644
index 0000000000..8cd2ee94d4
--- /dev/null
+++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketClientUnitTest.java
@@ -0,0 +1,82 @@
+package com.baeldung.socket;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.StandardProtocolFamily;
+import java.net.UnixDomainSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.file.Path;
+import java.util.UUID;
+
+import static java.nio.file.Files.deleteIfExists;
+import static org.assertj.core.util.Files.newTemporaryFile;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class UnixDomainSocketClientUnitTest {
+
+    @Test
+    public void givenSocketPath_shouldCreateUnixDomainSocketAddress() {
+        // given
+        File tempFile = newTemporaryFile();
+        Path socketPath = tempFile.toPath();
+
+        // when
+        UnixDomainSocketAddress address = new UnixDomainSocketClient().getAddress(socketPath);
+
+        // then
+        assertEquals(address.getPath(), socketPath);
+
+        // cleanup
+        tempFile.delete();
+    }
+
+    @Test
+    public void givenUnixDomainSocketAddress_shouldOpenSocketChannel() throws IOException {
+        // given
+        File tempFile = newTemporaryFile();
+        Path socketPath = tempFile.toPath();
+        deleteIfExists(socketPath);
+        UnixDomainSocketAddress address = UnixDomainSocketAddress.of(socketPath);
+
+        // bind address as a unix domain socket
+        ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
+        serverChannel.bind(address);
+
+        // when
+        SocketChannel socketChannel = new UnixDomainSocketClient().openSocketChannel(address);
+
+        // then
+        assertTrue(socketChannel.isOpen());
+        assertEquals(socketChannel.getRemoteAddress(), address);
+
+        // cleanup
+        tempFile.delete();
+    }
+
+    @Test
+    public void givenSocketChannelAndMessage_shouldWriteMessage() throws IOException {
+        // given
+        SocketChannel socketChannel = Mockito.mock(SocketChannel.class);
+        String message = UUID.randomUUID().toString();
+        Mockito.when(socketChannel.write(Mockito.any(ByteBuffer.class)))
+          .thenAnswer(
+            (Answer) invocationOnMock -> {
+              ((ByteBuffer) invocationOnMock.getArguments()[0]).position(message.getBytes().length);
+              return -1;
+            }
+          );
+
+        // when
+        new UnixDomainSocketClient().writeMessage(socketChannel, message);
+
+        // then
+        Mockito.verify(socketChannel, Mockito.times(1)).write(Mockito.any(ByteBuffer.class));
+    }
+}
diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketServerUnitTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketServerUnitTest.java
new file mode 100644
index 0000000000..1d0a68ac2f
--- /dev/null
+++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/UnixDomainSocketServerUnitTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.socket;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.UnixDomainSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.file.Path;
+
+import static java.nio.file.Files.deleteIfExists;
+import static org.assertj.core.util.Files.newTemporaryFile;
+import static org.junit.Assert.assertEquals;
+
+public class UnixDomainSocketServerUnitTest {
+
+    @Test
+    public void givenSocketPath_shouldCreateUnixDomainSocketAddress() {
+        // given
+        File tempFile = newTemporaryFile();
+        Path socketPath = tempFile.toPath();
+
+        // when
+        UnixDomainSocketAddress address = new UnixDomainSocketServer().getAddress(socketPath);
+
+        // then
+        assertEquals(address.getPath(), socketPath);
+
+        // cleanup
+        tempFile.delete();
+    }
+
+    @Test
+    public void givenUnixDomainSocketAddress_shouldCreateServerSocketChannel() throws IOException {
+        // given
+        File tempFile = newTemporaryFile();
+        Path socketPath = tempFile.toPath();
+        deleteIfExists(socketPath);
+        UnixDomainSocketAddress address = UnixDomainSocketAddress.of(socketPath);
+
+        // when
+        ServerSocketChannel serverSocketChannel = new UnixDomainSocketServer().createServerSocketChannel(address);
+
+        // then
+        assertEquals(serverSocketChannel.getLocalAddress(), address);
+
+        // cleanup
+        tempFile.delete();
+    }
+}
diff --git a/core-java-modules/core-java-nio-2/README.md b/core-java-modules/core-java-nio-2/README.md
index 52efa0330a..9152a494d8 100644
--- a/core-java-modules/core-java-nio-2/README.md
+++ b/core-java-modules/core-java-nio-2/README.md
@@ -11,4 +11,5 @@ This module contains articles about core Java non-blocking input and output (IO)
 - [How to Lock a File in Java](https://www.baeldung.com/java-lock-files)
 - [Java NIO DatagramChannel](https://www.baeldung.com/java-nio-datagramchannel)
 - [Java – Path vs File](https://www.baeldung.com/java-path-vs-file)
+- [What Is the Difference Between NIO and NIO.2?](https://www.baeldung.com/java-nio-vs-nio-2)
 - [[<-- Prev]](/core-java-modules/core-java-nio)
diff --git a/core-java-modules/core-java-nio-2/pom.xml b/core-java-modules/core-java-nio-2/pom.xml
index f9cf1f3060..eb56c2bf68 100644
--- a/core-java-modules/core-java-nio-2/pom.xml
+++ b/core-java-modules/core-java-nio-2/pom.xml
@@ -14,13 +14,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            3.6.1
-            test
-        
-    
-
 
\ No newline at end of file
diff --git a/guest/webservices/rest-server/src/main/resources/logback.xml b/core-java-modules/core-java-nio-2/src/main/resources/logback.xml
similarity index 100%
rename from guest/webservices/rest-server/src/main/resources/logback.xml
rename to core-java-modules/core-java-nio-2/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/niovsnio2/NioVsNio2UnitTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/niovsnio2/NioVsNio2UnitTest.java
new file mode 100644
index 0000000000..7413ebda13
--- /dev/null
+++ b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/niovsnio2/NioVsNio2UnitTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.niovsnio2;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class NioVsNio2UnitTest {
+
+    @Test
+    public void readFromFileUsingFileIO() throws Exception {
+        File file = new File("src/test/resources/nio-vs-nio2.txt");
+        FileInputStream in = new FileInputStream(file);
+        StringBuilder content = new StringBuilder();
+        int data = in.read();
+        while (data != -1) {
+            content.append((char) data);
+            data = in.read();
+        }
+        in.close();
+        assertThat(content.toString()).isEqualTo("Hello from file!");
+    }
+
+    @Test
+    public void readFromFileUsingFileChannel() throws Exception {
+        RandomAccessFile file = new RandomAccessFile("src/test/resources/nio-vs-nio2.txt", "r");
+        FileChannel channel = file.getChannel();
+        StringBuilder content = new StringBuilder();
+
+        ByteBuffer buffer = ByteBuffer.allocate(256);
+        int bytesRead = channel.read(buffer);
+        while (bytesRead != -1) {
+            buffer.flip();
+
+            while (buffer.hasRemaining()) {
+                content.append((char) buffer.get());
+            }
+
+            buffer.clear();
+            bytesRead = channel.read(buffer);
+        }
+        file.close();
+
+        assertThat(content.toString()).isEqualTo("Hello from file!");
+    }
+
+    @Test
+    public void readFromFileUsingNIO2() throws Exception {
+        List strings = Files.readAllLines(Paths.get("src/test/resources/nio-vs-nio2.txt"));
+
+        assertThat(strings.get(0)).isEqualTo("Hello from file!");
+    }
+
+    @Test
+    public void listFilesUsingWalk() throws Exception {
+        Path path = Paths.get("src/test");
+        Stream walk = Files.walk(path);
+        walk.forEach(System.out::println);
+    }
+}
diff --git a/core-java-modules/core-java-nio-2/src/test/resources/nio-vs-nio2.txt b/core-java-modules/core-java-nio-2/src/test/resources/nio-vs-nio2.txt
new file mode 100644
index 0000000000..c12b07297d
--- /dev/null
+++ b/core-java-modules/core-java-nio-2/src/test/resources/nio-vs-nio2.txt
@@ -0,0 +1 @@
+Hello from file!
\ No newline at end of file
diff --git a/core-java-modules/core-java-optional/pom.xml b/core-java-modules/core-java-optional/pom.xml
index dd5217df74..08441f6cee 100644
--- a/core-java-modules/core-java-optional/pom.xml
+++ b/core-java-modules/core-java-optional/pom.xml
@@ -45,29 +45,16 @@
             jmh-generator-bytecode
             ${jmh-generator.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             io.rest-assured
             json-path
             ${rest-assured.version}
             test
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
         5.4.0.Final
-        27.1-jre
-        3.10.0
         3.1.1
     
 
diff --git a/core-java-modules/core-java-os/pom.xml b/core-java-modules/core-java-os/pom.xml
index b279e3d6cb..0c6c921df9 100644
--- a/core-java-modules/core-java-os/pom.xml
+++ b/core-java-modules/core-java-os/pom.xml
@@ -1,99 +1,87 @@
 
 
-	4.0.0
-	core-java-os
-	0.1.0-SNAPSHOT
-	core-java-os
-	jar
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    4.0.0
+    core-java-os
+    0.1.0-SNAPSHOT
+    core-java-os
+    jar
 
-	
-		com.baeldung.core-java-modules
-		core-java-modules
-		0.0.1-SNAPSHOT
-		../
-	
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
 
-	
-	    
-		    org.junit.jupiter
-			junit-jupiter-engine
-            ${junit-jupiter.version}
-			test
-		
-		
-			org.apache.commons
-			commons-collections4
-			${commons-collections4.version}
-		
-		
-			commons-io
-			commons-io
-			${commons-io.version}
-		
-		
-			org.apache.commons
-			commons-lang3
-			${commons-lang3.version}
-		
-		
-			log4j
-			log4j
-			${log4j.version}
-		
-		
-		
-			org.assertj
-			assertj-core
-			${assertj.version}
-			test
-		
-		
-			org.unix4j
-			unix4j-command
-			${unix4j.version}
-		
-		
-			com.googlecode.grep4j
-			grep4j
-			${grep4j.version}
-		
-	
+    
+        
+            org.apache.commons
+            commons-collections4
+            ${commons-collections4.version}
+        
+        
+            commons-io
+            commons-io
+            ${commons-io.version}
+        
+        
+            org.apache.commons
+            commons-lang3
+            ${commons-lang3.version}
+        
+        
+            log4j
+            log4j
+            ${log4j.version}
+        
+        
+            org.unix4j
+            unix4j-command
+            ${unix4j.version}
+        
+        
+            com.googlecode.grep4j
+            grep4j
+            ${grep4j.version}
+        
+        
+            org.projectlombok
+            lombok
+            ${lombok.version}
+            provided
+        
+    
 
-	
-		core-java-os
-		
-			
-				src/main/resources
-				true
-			
-		
-		
-			
-				org.apache.maven.plugins
-				maven-compiler-plugin
-				${maven-compiler-plugin.version}
-				
-					${maven.compiler.source}
-					${maven.compiler.target}
-				
-			
-		
-	
+    
+        core-java-os
+        
+            
+                src/main/resources
+                true
+            
+        
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                ${maven-compiler-plugin.version}
+                
+                    ${maven.compiler.source}
+                    ${maven.compiler.target}
+                
+            
+        
+    
 
-	
-		
-		4.1
-		4.01
-		
-		3.6.1
-		1.8.9
-		1.9
-		1.9
-		25.1-jre
-		0.4
-		1.8.7
-	
+    
+        4.01
+        1.8.9
+        1.9
+        1.9
+        0.4
+        1.8.7
+        1.18.22
+    
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/shell/JavaProcessUnitIntegrationTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/shell/JavaProcessUnitIntegrationTest.java
index 53e9364207..9d24dd1578 100644
--- a/core-java-modules/core-java-os/src/test/java/com/baeldung/shell/JavaProcessUnitIntegrationTest.java
+++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/shell/JavaProcessUnitIntegrationTest.java
@@ -1,12 +1,23 @@
-package com.baeldung.java.shell;
+package com.baeldung.shell;
 
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
 public class JavaProcessUnitIntegrationTest {
     private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows");
 
@@ -29,6 +40,18 @@ public class JavaProcessUnitIntegrationTest {
 
     private String homeDirectory = System.getProperty("user.home");
 
+    private ExecutorService executorService;
+
+    @Before
+    public void setUp() {
+        executorService = Executors.newSingleThreadExecutor();
+    }
+
+    @After
+    public void tearDown() {
+        executorService.shutdown();
+    }
+
     @Test
     public void givenProcess_whenCreatingViaRuntime_shouldSucceed() throws Exception {
         Process process;
@@ -38,9 +61,13 @@ public class JavaProcessUnitIntegrationTest {
             process = Runtime.getRuntime().exec(String.format("sh -c ls %s", homeDirectory));
         }
         StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
-        Executors.newSingleThreadExecutor().submit(streamGobbler);
+
+        Future future = executorService.submit(streamGobbler);
         int exitCode = process.waitFor();
-        Assert.assertEquals(0, exitCode);
+
+        // verify the stream output from the process
+        assertDoesNotThrow(() -> future.get(10, TimeUnit.SECONDS));
+        assertEquals(0, exitCode);
     }
 
     @Test
@@ -54,8 +81,12 @@ public class JavaProcessUnitIntegrationTest {
         builder.directory(new File(homeDirectory));
         Process process = builder.start();
         StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
-        Executors.newSingleThreadExecutor().submit(streamGobbler);
+
+        Future future = executorService.submit(streamGobbler);
         int exitCode = process.waitFor();
-        Assert.assertEquals(0, exitCode);
+
+        // verify the stream output from the process
+        assertDoesNotThrow(() -> future.get(10, TimeUnit.SECONDS));
+        assertEquals(0, exitCode);
     }
 }
diff --git a/core-java-modules/core-java-perf/README.md b/core-java-modules/core-java-perf/README.md
index d52fd2d733..e09f8bb6fc 100644
--- a/core-java-modules/core-java-perf/README.md
+++ b/core-java-modules/core-java-perf/README.md
@@ -11,3 +11,4 @@ This module contains articles about performance of Java applications
 - [Monitoring Java Applications with Flight Recorder](https://www.baeldung.com/java-flight-recorder-monitoring)
 - [Branch Prediction in Java](https://www.baeldung.com/java-branch-prediction)
 - [Capturing a Java Thread Dump](https://www.baeldung.com/java-thread-dump)
+- [JMX Ports](https://www.baeldung.com/jmx-ports)
diff --git a/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/JMXConfiguration.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/JMXConfiguration.java
new file mode 100644
index 0000000000..e60ea253ed
--- /dev/null
+++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/JMXConfiguration.java
@@ -0,0 +1,10 @@
+package com.baeldung.jmx;
+
+public class JMXConfiguration {
+
+    public static void main(String[] args) {
+        while (true) {
+            // to ensure application does not terminate
+        }
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-reflection-2/README.md b/core-java-modules/core-java-reflection-2/README.md
index 4c888bdf58..c1966dd63d 100644
--- a/core-java-modules/core-java-reflection-2/README.md
+++ b/core-java-modules/core-java-reflection-2/README.md
@@ -6,3 +6,4 @@
 - [Checking if a Java Class is ‘abstract’ Using Reflection](https://www.baeldung.com/java-reflection-is-class-abstract)
 - [Invoking a Private Method in Java](https://www.baeldung.com/java-call-private-method)
 - [Finding All Classes in a Java Package](https://www.baeldung.com/java-find-all-classes-in-package)
+- [Invoke a Static Method Using Java Reflection API](https://www.baeldung.com/java-invoke-static-method-reflection)
diff --git a/core-java-modules/core-java-reflection-2/pom.xml b/core-java-modules/core-java-reflection-2/pom.xml
index 75168936a7..2cb6d722a8 100644
--- a/core-java-modules/core-java-reflection-2/pom.xml
+++ b/core-java-modules/core-java-reflection-2/pom.xml
@@ -24,12 +24,7 @@
         
             org.reflections
             reflections
-            0.9.12
-        
-        
-            com.google.guava
-            guava
-            30.1.1-jre
+            ${reflections.version}
         
     
 
@@ -56,7 +51,7 @@
     
 
     
-        3.8.0
+        0.9.12
         1.8
         1.8
         5.3.4
diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/access/staticmethods/GreetingAndBye.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/access/staticmethods/GreetingAndBye.java
new file mode 100644
index 0000000000..471ed1ee5b
--- /dev/null
+++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/access/staticmethods/GreetingAndBye.java
@@ -0,0 +1,12 @@
+package com.baeldung.reflection.access.staticmethods;
+
+public class GreetingAndBye {
+
+    public static String greeting(String name) {
+        return String.format("Hey %s, nice to meet you!", name);
+    }
+
+    private static String goodBye(String name) {
+        return String.format("Bye %s, see you next time.", name);
+    }
+}
diff --git a/guest/webservices/soap_client/src/main/resources/logback.xml b/core-java-modules/core-java-reflection-2/src/main/resources/logback.xml
similarity index 100%
rename from guest/webservices/soap_client/src/main/resources/logback.xml
rename to core-java-modules/core-java-reflection-2/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/GreetingAndByeClassUnitTest.java b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/GreetingAndByeClassUnitTest.java
new file mode 100644
index 0000000000..da82d2370c
--- /dev/null
+++ b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/GreetingAndByeClassUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.reflection.check.abstractclass;
+
+import com.baeldung.reflection.access.staticmethods.GreetingAndBye;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+class GreetingAndByeUnitTest {
+
+    @Test
+    void givenPublicStaticMethod_whenCallWithReflection_thenReturnExpectedResult() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class clazz = GreetingAndBye.class;
+        Method method = clazz.getMethod("greeting", String.class);
+        Object result = method.invoke(null, "Eric");
+        Assertions.assertEquals("Hey Eric, nice to meet you!", result);
+    }
+
+    @Test
+    void givenPrivateStaticMethod_whenCallWithReflection_thenReturnExpectedResult() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class clazz = GreetingAndBye.class;
+        Method method = clazz.getDeclaredMethod("goodBye", String.class);
+        method.setAccessible(true);
+        Object result = method.invoke(null, "Eric");
+        Assertions.assertEquals("Bye Eric, see you next time.", result);
+    }
+}
diff --git a/core-java-modules/core-java-reflection/README.md b/core-java-modules/core-java-reflection/README.md
index 62d8719981..7c3ef69012 100644
--- a/core-java-modules/core-java-reflection/README.md
+++ b/core-java-modules/core-java-reflection/README.md
@@ -3,7 +3,6 @@
 - [Void Type in Java](https://www.baeldung.com/java-void-type)
 - [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields)
 - [Method Parameter Reflection in Java](http://www.baeldung.com/java-parameter-reflection)
-- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
 - [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params)
 - [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies)
 - [What Causes java.lang.reflect.InvocationTargetException?](https://www.baeldung.com/java-lang-reflect-invocationtargetexception)
diff --git a/core-java-modules/core-java-reflection/pom.xml b/core-java-modules/core-java-reflection/pom.xml
index b28ecccb80..1706bf3c45 100644
--- a/core-java-modules/core-java-reflection/pom.xml
+++ b/core-java-modules/core-java-reflection/pom.xml
@@ -14,14 +14,6 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-        
-    
-
     
         core-java-reflection
         
@@ -45,8 +37,6 @@
     
 
     
-        3.8.0
-        3.10.0
         1.8
         1.8
     
diff --git a/core-java-modules/core-java-regex-2/README.md b/core-java-modules/core-java-regex-2/README.md
index 25656c3cb1..6dafc74d41 100644
--- a/core-java-modules/core-java-regex-2/README.md
+++ b/core-java-modules/core-java-regex-2/README.md
@@ -3,3 +3,5 @@
 - [Non-Capturing Regex Groups in Java](https://www.baeldung.com/java-regex-non-capturing-groups)
 - [Lookahead and Lookbehind in Java Regex](https://www.baeldung.com/java-regex-lookahead-lookbehind)
 - [Converting Camel Case and Title Case to Words in Java](https://www.baeldung.com/java-camel-case-title-case-to-words)
+- [How to Use Regular Expressions to Replace Tokens in Strings in Java](https://www.baeldung.com/java-regex-token-replacement)
+- More articles: [[<-- prev]](/core-java-modules/core-java-regex)
\ No newline at end of file
diff --git a/core-java-modules/core-java-regex-2/pom.xml b/core-java-modules/core-java-regex-2/pom.xml
index a47c0ff357..ae9385e63c 100644
--- a/core-java-modules/core-java-regex-2/pom.xml
+++ b/core-java-modules/core-java-regex-2/pom.xml
@@ -14,17 +14,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-    
-
-    
-        3.15.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-regex/src/main/java/com/baeldung/replacetokens/ReplacingTokens.java b/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/replacetokens/ReplacingTokens.java
similarity index 100%
rename from core-java-modules/core-java-regex/src/main/java/com/baeldung/replacetokens/ReplacingTokens.java
rename to core-java-modules/core-java-regex-2/src/main/java/com/baeldung/replacetokens/ReplacingTokens.java
diff --git a/core-java-modules/core-java-regex/src/test/java/com/baeldung/replacetokens/ReplacingTokensUnitTest.java b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/replacetokens/ReplacingTokensUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-regex/src/test/java/com/baeldung/replacetokens/ReplacingTokensUnitTest.java
rename to core-java-modules/core-java-regex-2/src/test/java/com/baeldung/replacetokens/ReplacingTokensUnitTest.java
diff --git a/core-java-modules/core-java-regex/README.md b/core-java-modules/core-java-regex/README.md
index 4c78f64d75..51c04af6ba 100644
--- a/core-java-modules/core-java-regex/README.md
+++ b/core-java-modules/core-java-regex/README.md
@@ -9,9 +9,9 @@
 - [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char)
 - [Pre-compile Regex Patterns Into Pattern Objects](https://www.baeldung.com/java-regex-pre-compile)
 - [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches)
-- [How to Use Regular Expressions to Replace Tokens in Strings in Java](https://www.baeldung.com/java-regex-token-replacement)
 - [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus)
 - [Validate Phone Numbers With Java Regex](https://www.baeldung.com/java-regex-validate-phone-numbers)
 - [How to Count the Number of Matches for a Regex?](https://www.baeldung.com/java-count-regex-matches)
 - [Find All Numbers in a String in Java](https://www.baeldung.com/java-find-numbers-in-string)
 - [Understanding the Pattern.quote Method](https://www.baeldung.com/java-pattern-quote)
+- More articles: [[next -->]](/core-java-modules/core-java-regex-2)
diff --git a/core-java-modules/core-java-regex/pom.xml b/core-java-modules/core-java-regex/pom.xml
index 3fb63fb42a..93f3ae3cdb 100644
--- a/core-java-modules/core-java-regex/pom.xml
+++ b/core-java-modules/core-java-regex/pom.xml
@@ -25,12 +25,6 @@
             jmh-generator-annprocess
             ${jmh-core.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
     
 
     
@@ -43,8 +37,4 @@
         
     
 
-    
-        3.15.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-regex/src/test/java/com/baeldung/regex/matcher/MatcherUnitTest.java b/core-java-modules/core-java-regex/src/test/java/com/baeldung/regex/matcher/MatcherUnitTest.java
index 304b9f2f1d..7ec4a1ae58 100644
--- a/core-java-modules/core-java-regex/src/test/java/com/baeldung/regex/matcher/MatcherUnitTest.java
+++ b/core-java-modules/core-java-regex/src/test/java/com/baeldung/regex/matcher/MatcherUnitTest.java
@@ -11,6 +11,9 @@ import org.junit.jupiter.api.Test;
 
 public class MatcherUnitTest {
 
+    private static final String STRING_INPUT = "test+";
+    private static final String REGEX = "\\+";
+
     @Test
     public void whenFindFourDigitWorks_thenCorrect() {
         Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d");
@@ -60,4 +63,16 @@ public class MatcherUnitTest {
         assertTrue(m.matches());// matches will always return the same return
     }
 
+    @Test
+    public void whenUsingMatcher_thenReturnTrue() {
+        Pattern pattern = Pattern.compile(REGEX);
+        Matcher matcher = pattern.matcher(STRING_INPUT);
+        assertTrue(matcher.find());
+    }
+
+    @Test
+    public void whenUsingMatches_thenReturnFalse() {
+        assertFalse(Pattern.matches(REGEX, STRING_INPUT));
+    }
+
 }
diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md
index 680a7de925..31404d24a5 100644
--- a/core-java-modules/core-java-security-2/README.md
+++ b/core-java-modules/core-java-security-2/README.md
@@ -10,12 +10,7 @@ This module contains articles about core Java Security
 - [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
 - [Checksums in Java](https://www.baeldung.com/java-checksums)
 - [How to Read PEM File to Get Public and Private Keys](https://www.baeldung.com/java-read-pem-file-keys)
-- [Listing the Available Cipher Algorithms](https://www.baeldung.com/java-list-cipher-algorithms)
 - [Get a List of Trusted Certificates in Java](https://www.baeldung.com/java-list-trusted-certificates)
 - [Security Context Basics: User, Subject and Principal](https://www.baeldung.com/security-context-basics)
-- [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption)
-- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception)
 - [The java.security.egd JVM Option](https://www.baeldung.com/java-security-egd)
-- [RSA in Java](https://www.baeldung.com/java-rsa)
-- [3DES in Java](https://www.baeldung.com/java-3des)
 - More articles: [[<-- prev]](/core-java-modules/core-java-security)
diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml
index 8de12c0c46..7a354ee9e2 100644
--- a/core-java-modules/core-java-security-2/pom.xml
+++ b/core-java-modules/core-java-security-2/pom.xml
@@ -25,13 +25,6 @@
             bcprov-jdk15on
             ${bouncycastle.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
         
             javax.xml.bind
@@ -41,11 +34,8 @@
     
 
     
-        
         1.60
         1.11
-        
-        3.18.0
         2.3.1
     
 
diff --git a/core-java-modules/core-java-security-3/README.md b/core-java-modules/core-java-security-3/README.md
index a37719964b..31969cd270 100644
--- a/core-java-modules/core-java-security-3/README.md
+++ b/core-java-modules/core-java-security-3/README.md
@@ -6,4 +6,8 @@ This module contains articles about core Java Security
 
 - [Secret Key and String Conversion in Java](https://www.baeldung.com/java-secret-key-to-string)
 - [Enabling Unlimited Strength Cryptography in Java](https://www.baeldung.com/jce-enable-unlimited-strength)
+- [Initialization Vector for Encryption](https://www.baeldung.com/java-encryption-iv)
+- [HMAC in Java](https://www.baeldung.com/java-hmac)
+- [Generating a Secure AES Key in Java](https://www.baeldung.com/java-secure-aes-key)
+- [Computing an X509 Certificate’s Thumbprint in Java](https://www.baeldung.com/java-x509-certificate-thumbprint)
 - More articles: [[<-- prev]](/core-java-modules/core-java-security-2)
diff --git a/core-java-modules/core-java-security-3/pom.xml b/core-java-modules/core-java-security-3/pom.xml
index 69d0ffb917..3cd546e697 100644
--- a/core-java-modules/core-java-security-3/pom.xml
+++ b/core-java-modules/core-java-security-3/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -26,13 +25,6 @@
             bcprov-jdk15on
             ${bouncycastle.version}
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
         
             javax.xml.bind
@@ -42,11 +34,8 @@
     
 
     
-        
         1.60
         1.11
-        
-        3.18.0
         2.3.1
     
 
diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/certificate/Thumbprint.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/certificate/Thumbprint.java
new file mode 100644
index 0000000000..7ccf1091c6
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/certificate/Thumbprint.java
@@ -0,0 +1,38 @@
+package com.baeldung.certificate;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import javax.xml.bind.DatatypeConverter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+public class Thumbprint {
+
+    public static void main(String[] args) throws CertificateException, IOException, NoSuchAlgorithmException {
+        X509Certificate certObject = getCertObject("baeldung.pem");
+        System.out.println(getThumbprint(certObject));
+    }
+
+    public static X509Certificate getCertObject(String filePath) throws IOException, CertificateException {
+        try (FileInputStream is = new FileInputStream(filePath)) {
+            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) certificateFactory.generateCertificate(is);
+        }
+    }
+
+    private static String getThumbprint(X509Certificate cert) throws NoSuchAlgorithmException, CertificateEncodingException {
+        MessageDigest md = MessageDigest.getInstance("SHA-1");
+        md.update(cert.getEncoded());
+        return DatatypeConverter.printHexBinary(md.digest()).toLowerCase();
+    }
+
+    private static String getThumbprintWithApache(X509Certificate cert) throws CertificateEncodingException {
+        return DigestUtils.sha1Hex(cert.getEncoded());
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java
new file mode 100644
index 0000000000..552bd5d474
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java
@@ -0,0 +1,86 @@
+package com.baeldung.crypto;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.GeneralSecurityException;
+
+import com.baeldung.crypto.utils.CryptoUtils;
+
+public class CryptoDriver {
+
+    public byte[] ecbEncrypt(SecretKey key, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, key);
+        return cipher.doFinal(data);
+    }
+
+    public byte[] ecbDecrypt(SecretKey key, byte[] cipherText) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+        cipher.init(Cipher.DECRYPT_MODE, key);
+        return cipher.doFinal(cipherText);
+    }
+
+    public byte[] cbcEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
+        return cipher.doFinal(data);
+    }
+
+    public byte[] cbcDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        cipher.init(Cipher.DECRYPT_MODE, key, iv);
+        return cipher.doFinal(cipherText);
+    }
+
+    public byte[] cfbEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
+        return cipher.doFinal(data);
+    }
+
+    public byte[] cfbDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
+        cipher.init(Cipher.DECRYPT_MODE, key, iv);
+        return cipher.doFinal(cipherText);
+    }
+
+    public byte[] ofbEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/OFB32/PKCS5Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
+        return cipher.doFinal(data);
+    }
+
+    public byte[] ofbDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/OFB32/PKCS5Padding");
+        cipher.init(Cipher.DECRYPT_MODE, key, iv);
+        return cipher.doFinal(cipherText);
+    }
+
+    public byte[][] ctrEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
+        return new byte[][] { cipher.getIV(), cipher.doFinal(data) };
+    }
+
+    public byte[] ctrDecrypt(SecretKey key, byte[] iv, byte[] cipherText) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
+        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+        return cipher.doFinal(cipherText);
+    }
+
+    public byte[][] gcmEncrypt(SecretKey key, byte[] iv, byte[] data) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));
+        byte[] ciphertext = cipher.doFinal(data);
+        return new byte[][] { iv, ciphertext };
+    }
+
+    public byte[] gcmDecrypt(SecretKey key, byte[] iv, byte[] ciphertext) throws GeneralSecurityException {
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
+        byte[] plaintext = cipher.doFinal(ciphertext);
+        return plaintext;
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java
new file mode 100644
index 0000000000..2d3df231ff
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java
@@ -0,0 +1,53 @@
+package com.baeldung.crypto.utils;
+
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidParameterSpecException;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+public class CryptoUtils {
+
+    public static SecretKey generateKey() throws GeneralSecurityException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+        keyGenerator.init(256);
+        return keyGenerator.generateKey();
+    }
+
+    public static IvParameterSpec getIV() {
+        SecureRandom secureRandom = new SecureRandom();
+        byte[] iv = new byte[128 / 8];
+        byte[] nonce = new byte[96 / 8];
+        secureRandom.nextBytes(nonce);
+        System.arraycopy(nonce, 0, iv, 0, nonce.length);
+        return new IvParameterSpec(nonce);
+    }
+
+    public static IvParameterSpec getIVSecureRandom(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {
+        SecureRandom random = SecureRandom.getInstanceStrong();
+        byte[] iv = new byte[Cipher.getInstance(algorithm)
+            .getBlockSize()];
+        random.nextBytes(iv);
+        return new IvParameterSpec(iv);
+    }
+
+    public static IvParameterSpec getIVInternal(Cipher cipher) throws InvalidParameterSpecException {
+        AlgorithmParameters params = cipher.getParameters();
+        byte[] iv = params.getParameterSpec(IvParameterSpec.class)
+            .getIV();
+        return new IvParameterSpec(iv);
+    }
+
+    public static byte[] getRandomIVWithSize(int size) {
+        byte[] nonce = new byte[size];
+        new SecureRandom().nextBytes(nonce);
+        return nonce;
+    }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/hmac/HMACUtil.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/hmac/HMACUtil.java
new file mode 100644
index 0000000000..3b504d9338
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/hmac/HMACUtil.java
@@ -0,0 +1,68 @@
+package com.baeldung.hmac;
+
+import org.apache.commons.codec.digest.HmacUtils;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.digests.SHA384Digest;
+import org.bouncycastle.crypto.digests.SHA512Digest;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+
+public class HMACUtil {
+
+    public static String hmacWithJava(String algorithm, String data, String key)
+        throws NoSuchAlgorithmException, InvalidKeyException {
+        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
+        Mac mac = Mac.getInstance(algorithm);
+        mac.init(secretKeySpec);
+        return bytesToHex(mac.doFinal(data.getBytes()));
+    }
+
+    public static String hmacWithApacheCommons(String algorithm, String data, String key) {
+        String hmac = new HmacUtils(algorithm, key).hmacHex(data);
+        return hmac;
+    }
+
+    public static String hmacWithBouncyCastle(String algorithm, String data, String key) {
+        Digest digest = getHashDigest(algorithm);
+        HMac hMac = new HMac(digest);
+        hMac.init(new KeyParameter(key.getBytes()));
+        byte[] hmacIn = data.getBytes();
+        hMac.update(hmacIn, 0, hmacIn.length);
+        byte[] hmacOut = new byte[hMac.getMacSize()];
+        hMac.doFinal(hmacOut, 0);
+        return bytesToHex(hmacOut);
+    }
+
+    private static Digest getHashDigest(String algorithm) {
+        switch (algorithm) {
+          case "HmacMD5":
+            return new MD5Digest();
+          case "HmacSHA256":
+            return new SHA256Digest();
+          case "HmacSHA384":
+            return new SHA384Digest();
+          case "HmacSHA512":
+            return new SHA512Digest();
+        }
+        return new SHA256Digest();
+    }
+
+    public static String bytesToHex(byte[] hash) {
+        StringBuilder hexString = new StringBuilder(2 * hash.length);
+        for (byte h : hash) {
+          String hex = Integer.toHexString(0xff & h);
+          if (hex.length() == 1)
+            hexString.append('0');
+          hexString.append(hex);
+        }
+        return hexString.toString();
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkey/Main.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkey/Main.java
new file mode 100644
index 0000000000..a7b1485150
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkey/Main.java
@@ -0,0 +1,99 @@
+package com.baeldung.secretkey;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Base64;
+import java.util.Random;
+
+import static javax.crypto.Cipher.ENCRYPT_MODE;
+
+public class Main {
+    private static final Logger logger = LoggerFactory.getLogger(Main.class);
+
+    private static final String CIPHER = "AES";
+
+    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
+        String plainText = "How you doing Mike?";
+
+        encrypt(plainText, getRandomKey(CIPHER, 128));
+        encrypt(plainText, getRandomKey(CIPHER, 192));
+        encrypt(plainText, getRandomKey(CIPHER, 256));
+
+        encrypt(plainText, getSecureRandomKey(CIPHER, 128));
+        encrypt(plainText, getSecureRandomKey(CIPHER, 192));
+        encrypt(plainText, getSecureRandomKey(CIPHER, 256));
+
+        encrypt(plainText, getKeyFromKeyGenerator(CIPHER, 128));
+        encrypt(plainText, getKeyFromKeyGenerator(CIPHER, 192));
+        encrypt(plainText, getKeyFromKeyGenerator(CIPHER, 256));
+
+        encrypt(plainText, getPasswordBasedKey(CIPHER, 128, new char[] { 'R', 'a', 'n', 'd', 'o', 'm' }));
+        encrypt(plainText, getPasswordBasedKey(CIPHER, 192, new char[] { 'R', 'a', 'n', 'd', 'o', 'm' }));
+        encrypt(plainText, getPasswordBasedKey(CIPHER, 256, new char[] { 'R', 'a', 'n', 'd', 'o', 'm' }));
+
+        try {
+            encrypt(plainText, getSecureRandomKey(CIPHER, 111));
+        } catch (InvalidKeyException e) {
+            logger.error("Unable to generate key", e);
+        }
+
+        try {
+            encrypt(plainText, getKeyFromKeyGenerator(CIPHER, 111));
+        } catch (InvalidParameterException e) {
+            logger.error("Unable to generate key", e);
+        }
+    }
+
+    private static void encrypt(String plainText, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        cipher.init(ENCRYPT_MODE, key);
+        byte[] cipherTextBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+        logger.info(Base64.getEncoder().encodeToString(cipherTextBytes));
+    }
+
+    private static Key getRandomKey(String cipher, int keySize) {
+        byte[] randomKeyBytes = new byte[keySize / 8];
+        Random random = new Random();
+        random.nextBytes(randomKeyBytes);
+        return new SecretKeySpec(randomKeyBytes, cipher);
+    }
+
+    private static Key getSecureRandomKey(String cipher, int keySize) {
+        byte[] secureRandomKeyBytes = new byte[keySize / 8];
+        SecureRandom secureRandom = new SecureRandom();
+        secureRandom.nextBytes(secureRandomKeyBytes);
+        return new SecretKeySpec(secureRandomKeyBytes, cipher);
+    }
+
+    private static Key getKeyFromKeyGenerator(String cipher, int keySize) throws NoSuchAlgorithmException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(cipher);
+        keyGenerator.init(keySize);
+        return keyGenerator.generateKey();
+    }
+
+    private static Key getPasswordBasedKey(String cipher, int keySize, char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        byte[] salt = new byte[100];
+        SecureRandom random = new SecureRandom();
+        random.nextBytes(salt);
+        PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 100000, keySize);
+        SecretKey pbeKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(pbeKeySpec);
+        return new SecretKeySpec(pbeKey.getEncoded(), cipher);
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java
new file mode 100644
index 0000000000..f3bed310dd
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java
@@ -0,0 +1,86 @@
+package com.baeldung.crypto;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.GeneralSecurityException;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.crypto.utils.CryptoUtils;
+
+public class CryptoDriverIVUnitTest{
+    private CryptoDriver driver = new CryptoDriver();
+    private String TEST_DATA = "Encrypt this for testing";
+
+    @Test
+    public void givenString_whenAesEcb_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        byte[] plaintext = TEST_DATA.getBytes();
+
+        byte[] ciphertext = driver.ecbEncrypt(key, plaintext);
+        byte[] decryptedtext = driver.ecbDecrypt(key, ciphertext);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+
+    @Test
+    public void givenString_whenAesCbc_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES");
+        byte[] plaintext = TEST_DATA.getBytes();
+
+        byte[] ciphertext = driver.cbcEncrypt(key, iv, plaintext);
+        byte[] decryptedtext = driver.cbcDecrypt(key, iv, ciphertext);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+
+    @Test
+    public void givenString_whenAesCfb_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/CFB/NoPadding");
+        byte[] plaintext = TEST_DATA.getBytes();
+
+        byte[] ciphertext = driver.cfbEncrypt(key, iv, plaintext);
+        byte[] decryptedtext = driver.cfbDecrypt(key, iv, ciphertext);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+
+    @Test
+    public void givenString_whenAesOfb_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/OFB32/PKCS5Padding");
+        byte[] plaintext = TEST_DATA.getBytes();
+
+        byte[] ciphertext = driver.ofbEncrypt(key, iv, plaintext);
+        byte[] decryptedtext = driver.ofbDecrypt(key, iv, ciphertext);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+
+    @Test
+    public void givenString_whenAesCtr_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/CTR/NoPadding");
+        byte[] plaintext = TEST_DATA.getBytes();
+
+        byte[][] ciphertext = driver.ctrEncrypt(key, iv, plaintext);
+        byte[] decryptedtext = driver.ctrDecrypt(key, ciphertext[0], ciphertext[1]);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+
+    @Test
+    void givenString_whenAesGcm_thenSuccess() throws GeneralSecurityException {
+        SecretKey key = CryptoUtils.generateKey();
+        byte[] iv = CryptoUtils.getRandomIVWithSize(12);
+        byte[] plaintext = (TEST_DATA).getBytes();
+
+        byte[][] ciphertext = driver.gcmEncrypt(key, iv, plaintext);
+        byte[] decryptedtext = driver.gcmDecrypt(key, ciphertext[0], ciphertext[1]);
+
+        Assertions.assertEquals(new String(decryptedtext), TEST_DATA);
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/test/java/com/baeldung/hmac/HMACUtilUnitTest.java b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/hmac/HMACUtilUnitTest.java
new file mode 100644
index 0000000000..0d7f97a094
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/hmac/HMACUtilUnitTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.hmac;
+
+import org.junit.Test;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import static org.junit.Assert.assertEquals;
+
+public class HMACUtilUnitTest {
+
+    @Test
+    public void givenDataAndKeyAndAlgorithm_whenHmacWithJava_thenSuccess()
+        throws NoSuchAlgorithmException, InvalidKeyException {
+
+        //given
+        String hmacSHA256Value = "5b50d80c7dc7ae8bb1b1433cc0b99ecd2ac8397a555c6f75cb8a619ae35a0c35";
+        String hmacSHA256Algorithm = "HmacSHA256";
+        String data = "baeldung";
+        String key = "123456";
+
+        //when
+        String result = HMACUtil.hmacWithJava(hmacSHA256Algorithm, data, key);
+
+        //then
+        assertEquals(hmacSHA256Value, result);
+    }
+
+    @Test
+    public void givenDataAndKeyAndAlgorithm_whenHmacWithApacheCommons_thenSuccess() {
+
+        //given
+        String hmacMD5Value = "621dc816b3bf670212e0c261dc9bcdb6";
+        String hmacMD5Algorithm = "HmacMD5";
+        String data = "baeldung";
+        String key = "123456";
+
+        //when
+        String result = HMACUtil.hmacWithApacheCommons(hmacMD5Algorithm, data, key);
+
+        //then
+        assertEquals(hmacMD5Value, result);
+    }
+
+    @Test
+    public void givenDataAndKeyAndAlgorithm_whenHmacWithBouncyCastle_thenSuccess() {
+
+        //given
+        String hmacSHA512Value = "b313a21908df55c9e322e3c65a4b0b7561ab1594ca806b3affbc0d769a1" +
+          "290c1922aa6622587bea3c0c4d871470a6d06f54dbd20dbda84250e2741eb01f08e33";
+        String hmacSHA512Algorithm = "HmacSHA512";
+        String data = "baeldung";
+        String key = "123456";
+
+        //when
+        String result = HMACUtil.hmacWithBouncyCastle(hmacSHA512Algorithm, data, key);
+
+        //then
+        assertEquals(hmacSHA512Value, result);
+    }
+}
diff --git a/core-java-modules/core-java-security-3/src/test/java/com/baeldung/truststore/TrustStoreUnitTest.java b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/truststore/TrustStoreUnitTest.java
new file mode 100644
index 0000000000..2c3d4c8959
--- /dev/null
+++ b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/truststore/TrustStoreUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.truststore;
+
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.PKIXParameters;
+
+public class TrustStoreUnitTest {
+
+    @Test
+    public void whenOpeningTrustStore_thenExceptionIsThrown() throws Exception {
+        KeyStore keyStore = getKeyStore();
+        InvalidAlgorithmParameterException invalidAlgorithmParameterException =
+          Assertions.assertThrows(InvalidAlgorithmParameterException.class, () -> new PKIXParameters(keyStore));
+        Assertions.assertEquals("the trustAnchors parameter must be non-empty", invalidAlgorithmParameterException.getMessage());
+    }
+
+    private KeyStore getKeyStore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        ks.load(null, "changeIt".toCharArray());
+        return ks;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-algorithms/README.md b/core-java-modules/core-java-security-algorithms/README.md
new file mode 100644
index 0000000000..a1ce244ab8
--- /dev/null
+++ b/core-java-modules/core-java-security-algorithms/README.md
@@ -0,0 +1,11 @@
+## Core Java Security Algorithms
+
+This module contains articles about core Java Security Algorithms such as AES, DES, RSA, etc
+
+### Relevant Articles:
+
+- [Listing the Available Cipher Algorithms](https://www.baeldung.com/java-list-cipher-algorithms)
+- [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption)
+- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception)
+- [RSA in Java](https://www.baeldung.com/java-rsa)
+- [3DES in Java](https://www.baeldung.com/java-3des)
diff --git a/core-java-modules/core-java-security-algorithms/pom.xml b/core-java-modules/core-java-security-algorithms/pom.xml
new file mode 100644
index 0000000000..967ddc103e
--- /dev/null
+++ b/core-java-modules/core-java-security-algorithms/pom.xml
@@ -0,0 +1,42 @@
+
+
+    4.0.0
+    core-java-security-algorithms
+    0.1.0-SNAPSHOT
+    core-java-security-algorithms
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        
+            commons-codec
+            commons-codec
+            ${commons-codec.version}
+        
+        
+            org.bouncycastle
+            bcprov-jdk15on
+            ${bouncycastle.version}
+        
+        
+        
+            javax.xml.bind
+            jaxb-api
+            ${jaxb-api.version}
+        
+    
+
+    
+        1.60
+        1.11
+        2.3.1
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/AESUtil.java b/core-java-modules/core-java-security-algorithms/src/main/java/com/baeldung/aes/AESUtil.java
similarity index 100%
rename from core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/AESUtil.java
rename to core-java-modules/core-java-security-algorithms/src/main/java/com/baeldung/aes/AESUtil.java
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/Student.java b/core-java-modules/core-java-security-algorithms/src/main/java/com/baeldung/aes/Student.java
similarity index 100%
rename from core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/Student.java
rename to core-java-modules/core-java-security-algorithms/src/main/java/com/baeldung/aes/Student.java
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/aes/AESUtilUnitTest.java b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/aes/AESUtilUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-security-2/src/test/java/com/baeldung/aes/AESUtilUnitTest.java
rename to core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/aes/AESUtilUnitTest.java
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/cipher/AvailableCiphersUnitTest.java b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/cipher/AvailableCiphersUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-security-2/src/test/java/com/baeldung/cipher/AvailableCiphersUnitTest.java
rename to core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/cipher/AvailableCiphersUnitTest.java
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/des/TripleDESUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java
rename to core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/des/TripleDESUnitTest.java
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/rsa/RsaUnitTest.java b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/rsa/RsaUnitTest.java
similarity index 99%
rename from core-java-modules/core-java-security-2/src/test/java/com/baeldung/rsa/RsaUnitTest.java
rename to core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/rsa/RsaUnitTest.java
index ac93f71125..9659fd8871 100644
--- a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/rsa/RsaUnitTest.java
+++ b/core-java-modules/core-java-security-algorithms/src/test/java/com/baeldung/rsa/RsaUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.cipher;
+package com.baeldung.rsa;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/core-java-modules/core-java-security-2/src/test/resources/baeldung.txt b/core-java-modules/core-java-security-algorithms/src/test/resources/baeldung.txt
similarity index 100%
rename from core-java-modules/core-java-security-2/src/test/resources/baeldung.txt
rename to core-java-modules/core-java-security-algorithms/src/test/resources/baeldung.txt
diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml
index daba990776..b36de5ac4c 100644
--- a/core-java-modules/core-java-security/pom.xml
+++ b/core-java-modules/core-java-security/pom.xml
@@ -14,19 +14,4 @@
         0.0.1-SNAPSHOT
     
 
-    
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
-    
-
-    
-        
-        3.10.0
-    
-
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-serialization/README.md b/core-java-modules/core-java-serialization/README.md
new file mode 100644
index 0000000000..fc6cfcf134
--- /dev/null
+++ b/core-java-modules/core-java-serialization/README.md
@@ -0,0 +1,9 @@
+## Core Java Serialization
+
+### Relevant Articles: 
+  
+- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)
+- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
+- [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities)
+- [Serialization Validation in Java](https://www.baeldung.com/java-validate-serializable)
+- [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid)
diff --git a/core-java-modules/core-java-serialization/pom.xml b/core-java-modules/core-java-serialization/pom.xml
new file mode 100644
index 0000000000..315ed8cdad
--- /dev/null
+++ b/core-java-modules/core-java-serialization/pom.xml
@@ -0,0 +1,180 @@
+
+
+    4.0.0
+    core-java-serialization
+    0.1.0-SNAPSHOT
+    core-java-serialization
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        
+            org.unix4j
+            unix4j-command
+            ${unix4j.version}
+        
+        
+            com.googlecode.grep4j
+            grep4j
+            ${grep4j.version}
+        
+        
+        
+        
+            com.fasterxml.jackson.core
+            jackson-databind
+            ${jackson.version}
+        
+        
+        
+            log4j
+            log4j
+            ${log4j.version}
+        
+         
+            org.slf4j
+            log4j-over-slf4j
+            ${org.slf4j.version}
+        
+        
+            org.springframework
+            spring-core
+            ${spring.core.version}
+        
+        
+            org.springframework
+            spring-core
+            ${spring.core.version}
+            test
+        
+    
+
+    
+        core-java-serialization
+        
+            
+                src/main/resources
+                true
+            
+        
+
+        
+            
+                org.apache.maven.plugins
+                maven-dependency-plugin
+                
+                    
+                        copy-dependencies
+                        prepare-package
+                        
+                            copy-dependencies
+                        
+                        
+                            ${project.build.directory}/libs
+                        
+                    
+                
+            
+            
+                org.codehaus.mojo
+                exec-maven-plugin
+                
+                    java
+                    com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
+                    
+                        -Xmx300m
+                        -XX:+UseParallelGC
+                        -classpath
+                        
+                        com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
+                    
+                
+            
+            
+                org.apache.maven.plugins
+                maven-javadoc-plugin
+                ${maven-javadoc-plugin.version}
+                
+                    ${source.version}
+                    ${target.version}
+                
+            
+        
+    
+
+    
+        
+            integration
+            
+                
+                    
+                        org.apache.maven.plugins
+                        maven-surefire-plugin
+                        
+                            
+                                integration-test
+                                
+                                    test
+                                
+                                
+                                    
+                                        **/*ManualTest.java
+                                    
+                                    
+                                        **/*IntegrationTest.java
+                                        **/*IntTest.java
+                                    
+                                
+                            
+                        
+                        
+                            
+                                json
+                            
+                        
+                    
+                    
+                        org.codehaus.mojo
+                        exec-maven-plugin
+                        
+                            
+                                run-benchmarks
+                                
+                                none
+                                
+                                    exec
+                                
+                                
+                                    test
+                                    java
+                                    
+                                        -classpath
+                                        
+                                        org.openjdk.jmh.Main
+                                        .*
+                                    
+                                
+                            
+                        
+                    
+                
+            
+        
+    
+
+    
+        0.4
+        1.8.7
+        1.1
+        3.0.0-M1
+        4.3.20.RELEASE
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/AppleProduct.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/AppleProduct.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DefaultSerial.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DefaultSerial.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DefaultSerial.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DefaultSerial.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DeserializationUtility.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DeserializationUtility.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/SerializationUtility.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/SerializationUtility.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Community.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Community.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Community.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Community.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Country.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Country.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Country.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Country.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Region.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Region.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Region.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Region.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Address.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Address.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/serialization/Address.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Address.java
diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java
new file mode 100644
index 0000000000..51587b6c86
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java
@@ -0,0 +1,35 @@
+package com.baeldung.serialization;
+
+import java.io.Serializable;
+
+public class Customer implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private long id;
+    private volatile String name;
+    private Address address;
+
+    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 Address getAddress() {
+        return address;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+}
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Employee.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Employee.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/serialization/Employee.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Employee.java
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Person.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Person.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/serialization/Person.java
rename to core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Person.java
diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java
new file mode 100644
index 0000000000..568a503476
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java
@@ -0,0 +1,46 @@
+package com.baeldung.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+public class MySerializationUtils {
+
+    public static  byte[] serialize(T obj) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(obj);
+        oos.close();
+        return baos.toByteArray();
+    }
+
+    public static  T deserialize(byte[] b, Class cl) throws IOException, ClassNotFoundException {
+        ByteArrayInputStream bais = new ByteArrayInputStream(b);
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        Object o = ois.readObject();
+        return cl.cast(o);
+    }
+
+    public static boolean isSerializable(Class it) {
+        boolean serializable = it.isPrimitive() || it.isInterface() || Serializable.class.isAssignableFrom(it);
+        if (!serializable) {
+            return false;
+        }
+        Field[] declaredFields = it.getDeclaredFields();
+        for (Field field : declaredFields) {
+            if (Modifier.isVolatile(field.getModifiers()) || Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            Class fieldType = field.getType();
+            if (!isSerializable(fieldType)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/core-java-modules/core-java-io/src/main/resources/log4j.properties b/core-java-modules/core-java-serialization/src/main/resources/log4j.properties
similarity index 100%
rename from core-java-modules/core-java-io/src/main/resources/log4j.properties
rename to core-java-modules/core-java-serialization/src/main/resources/log4j.properties
diff --git a/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml b/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..a824bef9b0
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+        
+    
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java-serialization/src/main/resources/log4jstructuraldp.properties
similarity index 100%
rename from core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties
rename to core-java-modules/core-java-serialization/src/main/resources/log4jstructuraldp.properties
diff --git a/core-java-modules/core-java-serialization/src/main/resources/logback.xml b/core-java-modules/core-java-serialization/src/main/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+    
+        
+            %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/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java
similarity index 99%
rename from core-java-modules/core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java
rename to core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java
index d7c1ee17d4..89a603a298 100644
--- a/core-java-modules/core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java
+++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
 import java.io.IOException;
 import java.io.InvalidClassException;
 
+import org.junit.Assert;
 import org.junit.Ignore;
 import org.junit.Test;
 
diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java
similarity index 69%
rename from core-java-modules/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java
rename to core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java
index 651364fb13..9012928d92 100644
--- a/core-java-modules/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java
+++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java
@@ -1,14 +1,29 @@
 package com.baeldung.externalizable;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 import java.io.*;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class ExternalizableUnitTest {
 
-    private final static String OUTPUT_FILE = "externalizable.txt";
+    private final static String OUTPUT_FILE_NAME = "externalizable.txt";
+
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    private File outputFile;
+
+    @Before
+    public void setUp() throws Exception {
+        outputFile = tempFolder.newFile(OUTPUT_FILE_NAME);
+    }
 
     @Test
     public void whenSerializing_thenUseExternalizable() throws IOException, ClassNotFoundException {
@@ -18,7 +33,7 @@ public class ExternalizableUnitTest {
         c.setCode(374);
         c.setName("Armenia");
 
-        FileOutputStream fileOutputStream = new FileOutputStream(OUTPUT_FILE);
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
         c.writeExternal(objectOutputStream);
 
@@ -26,7 +41,7 @@ public class ExternalizableUnitTest {
         objectOutputStream.close();
         fileOutputStream.close();
 
-        FileInputStream fileInputStream = new FileInputStream(OUTPUT_FILE);
+        FileInputStream fileInputStream = new FileInputStream(outputFile);
         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
 
         Country c2 = new Country();
@@ -35,8 +50,8 @@ public class ExternalizableUnitTest {
         objectInputStream.close();
         fileInputStream.close();
 
-        assertTrue(c2.getCode() == c.getCode());
-        assertTrue(c2.getName().equals(c.getName()));
+        assertEquals(c2.getCode(), c.getCode());
+        assertEquals(c2.getName(), c.getName());
     }
 
     @Test
@@ -49,7 +64,7 @@ public class ExternalizableUnitTest {
         r.setClimate("Mediterranean");
         r.setPopulation(120.000);
 
-        FileOutputStream fileOutputStream = new FileOutputStream(OUTPUT_FILE);
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
         r.writeExternal(objectOutputStream);
 
@@ -57,7 +72,7 @@ public class ExternalizableUnitTest {
         objectOutputStream.close();
         fileOutputStream.close();
 
-        FileInputStream fileInputStream = new FileInputStream(OUTPUT_FILE);
+        FileInputStream fileInputStream = new FileInputStream(outputFile);
         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
 
         Region r2 = new Region();
@@ -66,6 +81,6 @@ public class ExternalizableUnitTest {
         objectInputStream.close();
         fileInputStream.close();
 
-        assertTrue(r2.getPopulation() == null);
+        assertNull(r2.getPopulation());
     }
 }
diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java
similarity index 67%
rename from core-java-modules/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java
rename to core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java
index dbcdf0ec9d..47dc0b9293 100644
--- a/core-java-modules/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java
+++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java
@@ -1,36 +1,54 @@
 package com.baeldung.serialization;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class PersonUnitTest {
 
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    private File outputFile;
+
+    private File outputFile2;
+
+    @Before
+    public void setUp() throws Exception {
+        outputFile = tempFolder.newFile("yourfile.txt");
+        outputFile2 = tempFolder.newFile("yourfile2.txt");
+    }
+
     @Test
     public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException {
         Person p = new Person();
         p.setAge(20);
         p.setName("Joe");
 
-        FileOutputStream fileOutputStream = new FileOutputStream("yofile.txt");
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
         objectOutputStream.writeObject(p);
         objectOutputStream.flush();
         objectOutputStream.close();
 
-        FileInputStream fileInputStream = new FileInputStream("yofile.txt");
+        FileInputStream fileInputStream = new FileInputStream(outputFile);
         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
         Person p2 = (Person) objectInputStream.readObject();
         objectInputStream.close();
 
-        assertTrue(p2.getAge() == p.getAge());
-        assertTrue(p2.getName().equals(p.getName()));
+        assertEquals(p2.getAge(), p.getAge());
+        assertEquals(p2.getName(), p.getName());
     }
 
     @Test
@@ -46,19 +64,19 @@ public class PersonUnitTest {
         e.setPerson(p);
         e.setAddress(a);
 
-        FileOutputStream fileOutputStream = new FileOutputStream("yofile2.txt");
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile2);
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
         objectOutputStream.writeObject(e);
         objectOutputStream.flush();
         objectOutputStream.close();
 
-        FileInputStream fileInputStream = new FileInputStream("yofile2.txt");
+        FileInputStream fileInputStream = new FileInputStream(outputFile2);
         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
         Employee e2 = (Employee) objectInputStream.readObject();
         objectInputStream.close();
 
-        assertTrue(e2.getPerson().getAge() == e.getPerson().getAge());
-        assertTrue(e2.getAddress().getHouseNumber() == (e.getAddress().getHouseNumber()));
+        assertEquals(e2.getPerson().getAge(), e.getPerson().getAge());
+        assertEquals(e2.getAddress().getHouseNumber(), (e.getAddress().getHouseNumber()));
     }
 
 }
diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java
new file mode 100644
index 0000000000..a7cbc0599b
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java
@@ -0,0 +1,129 @@
+package com.baeldung.serialization;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.apache.commons.lang3.SerializationUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.baeldung.util.MySerializationUtils;
+import org.junit.rules.TemporaryFolder;
+
+public class SerializationUnitTest {
+
+    private final static String OUTPUT_FILE_NAME = "yourfile.txt";
+
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    private File outputFile;
+
+    @Before
+    public void setUp() throws Exception {
+        outputFile = tempFolder.newFile(OUTPUT_FILE_NAME);
+    }
+
+    @Test(expected = NotSerializableException.class)
+    public void whenSerializing_ThenThrowsError() throws IOException {
+        Address address = new Address();
+        address.setHouseNumber(10);
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
+        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
+            objectOutputStream.writeObject(address);
+        }
+    }
+
+    @Test
+    public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException {
+        Person p = new Person();
+        p.setAge(20);
+        p.setName("Joe");
+
+        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
+        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
+            objectOutputStream.writeObject(p);
+        }
+
+        FileInputStream fileInputStream = new FileInputStream(outputFile);
+        try (ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
+            Person p2 = (Person) objectInputStream.readObject();
+            assertEquals(p2.getAge(), p.getAge());
+            assertEquals(p2.getName(), p.getName());
+        }
+    }
+
+    @Test(expected = ClassCastException.class)
+    public void whenSerializingUsingApacheCommons_ThenThrowsError() {
+        Address address = new Address();
+        address.setHouseNumber(10);
+        SerializationUtils.serialize((Serializable) address);
+    }
+
+    @Test
+    public void whenSerializingAndDeserializingUsingApacheCommons_ThenObjectIsTheSame() {
+        Person p = new Person();
+        p.setAge(20);
+        p.setName("Joe");
+        byte[] serialize = SerializationUtils.serialize(p);
+        Person p2 = (Person) SerializationUtils.deserialize(serialize);
+        assertEquals(p2.getAge(), p.getAge());
+        assertEquals(p2.getName(), p.getName());
+    }
+
+    @Test(expected = ClassCastException.class)
+    public void whenSerializingUsingSpringSerializationUtils_ThenThrowsError() {
+        Address address = new Address();
+        address.setHouseNumber(10);
+        org.springframework.util.SerializationUtils.serialize((Serializable) address);
+    }
+
+    @Test
+    public void whenSerializingAndDeserializingUsingSpringSerializationUtils_ThenObjectIsTheSame() {
+        Person p = new Person();
+        p.setAge(20);
+        p.setName("Joe");
+        byte[] serialize = org.springframework.util.SerializationUtils.serialize(p);
+        Person p2 = (Person) org.springframework.util.SerializationUtils.deserialize(serialize);
+        assertEquals(p2.getAge(), p.getAge());
+        assertEquals(p2.getName(), p.getName());
+    }
+
+    @Test(expected = ClassCastException.class)
+    public void whenSerializingUsingCustomSerializationUtils_ThenThrowsError() throws IOException {
+        Address address = new Address();
+        address.setHouseNumber(10);
+        MySerializationUtils.serialize((Serializable) address);
+    }
+
+    @Test
+    public void whenSerializingAndDeserializingUsingCustomSerializationUtils_ThenObjectIsTheSame() throws IOException, ClassNotFoundException {
+        Person p = new Person();
+        p.setAge(20);
+        p.setName("Joe");
+        byte[] serialize = MySerializationUtils.serialize(p);
+        Person p2 = MySerializationUtils.deserialize(serialize, Person.class);
+        assertEquals(p2.getAge(), p.getAge());
+        assertEquals(p2.getName(), p.getName());
+    }
+
+    @Test
+    public void whenSerializingUsingCustomSerializationUtils_ThanOk() {
+        assertFalse(MySerializationUtils.isSerializable(Address.class));
+        assertTrue(MySerializationUtils.isSerializable(Person.class));
+        assertTrue(MySerializationUtils.isSerializable(Integer.class));
+        assertFalse(MySerializationUtils.isSerializable(Customer.class));
+        assertTrue(MySerializationUtils.isSerializable(Employee.class));
+    }
+}
diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4j.properties b/core-java-modules/core-java-serialization/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..621cf01735
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/test/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=DEBUG, A1
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml b/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000..a824bef9b0
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+        
+    
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties b/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties
new file mode 100644
index 0000000000..5bc2bfe4b9
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties
@@ -0,0 +1,9 @@
+
+# Root logger 
+log4j.rootLogger=INFO, file, stdout
+
+# Write to console
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-serialization/src/test/resources/logback.xml b/core-java-modules/core-java-serialization/src/test/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/core-java-modules/core-java-serialization/src/test/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+    
+        
+            %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-streams-2/pom.xml b/core-java-modules/core-java-streams-2/pom.xml
index 087a8378b1..c8fa83c55a 100644
--- a/core-java-modules/core-java-streams-2/pom.xml
+++ b/core-java-modules/core-java-streams-2/pom.xml
@@ -30,23 +30,11 @@
             log4j
             ${log4j.version}
         
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
         1.9
         1.9
-        3.11.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-3/pom.xml b/core-java-modules/core-java-streams-3/pom.xml
index b384ef7e0e..c2dfdc392b 100644
--- a/core-java-modules/core-java-streams-3/pom.xml
+++ b/core-java-modules/core-java-streams-3/pom.xml
@@ -29,19 +29,12 @@
         
             org.openjdk.jmh
             jmh-core
-            ${jmh.version}
+            ${jmh-core.version}
         
         
             org.openjdk.jmh
             jmh-generator-annprocess
-            ${jmh.version}
-            test
-        
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
+            ${jmh-generator.version}
             test
         
     
@@ -65,7 +58,7 @@
                         
                             org.openjdk.jmh
                             jmh-generator-annprocess
-                            ${jmh.version}
+                            ${jmh-generator.version}
                         
                     
                 
@@ -75,9 +68,6 @@
 
     
         1.18.20
-        
-        3.6.1
-        1.29
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams/pom.xml b/core-java-modules/core-java-streams/pom.xml
index 4862672c8a..a6bb827e77 100644
--- a/core-java-modules/core-java-streams/pom.xml
+++ b/core-java-modules/core-java-streams/pom.xml
@@ -43,13 +43,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.codepoetics
             protonpack
@@ -105,14 +98,11 @@
     
 
     
-        
         0.9.0
         1.15
         0.6.5
         2.10
         1.3
-        
-        3.11.1
         1.8.9
         3.1
         1.8
diff --git a/core-java-modules/core-java-string-algorithms-2/pom.xml b/core-java-modules/core-java-string-algorithms-2/pom.xml
index 4b0d55508f..5af187abc2 100644
--- a/core-java-modules/core-java-string-algorithms-2/pom.xml
+++ b/core-java-modules/core-java-string-algorithms-2/pom.xml
@@ -20,11 +20,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.openjdk.jmh
             jmh-core
@@ -35,12 +30,6 @@
             jmh-generator-annprocess
             ${jmh-generator.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.bitbucket.cowwoc
             diff-match-patch
@@ -60,7 +49,6 @@
     
 
     
-        3.6.1
         1.2
     
 
diff --git a/core-java-modules/core-java-string-algorithms-3/README.md b/core-java-modules/core-java-string-algorithms-3/README.md
index 8d515b9aea..ba8509306e 100644
--- a/core-java-modules/core-java-string-algorithms-3/README.md
+++ b/core-java-modules/core-java-string-algorithms-3/README.md
@@ -4,5 +4,7 @@ This module contains articles about string-related algorithms.
 
 ### Relevant Articles:
 
+- [Generating a Java String of N Repeated Characters](https://www.baeldung.com/java-string-of-repeated-characters)
 - [Check if Two Strings are Anagrams in Java](https://www.baeldung.com/java-strings-anagrams)
 - [Email Validation in Java](https://www.baeldung.com/java-email-validation-regex)
+- [Check if the First Letter of a String is Uppercase](https://www.baeldung.com/java-check-first-letter-uppercase)
diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml
index 6376bfa677..dc8ad3851d 100644
--- a/core-java-modules/core-java-string-algorithms-3/pom.xml
+++ b/core-java-modules/core-java-string-algorithms-3/pom.xml
@@ -4,8 +4,8 @@
     4.0.0
     core-java-string-algorithms-3
     0.1.0-SNAPSHOT
-    jar
     core-java-string-algorithms-3
+    jar
 
     
         com.baeldung.core-java-modules
@@ -14,28 +14,16 @@
     
 
     
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
-        
-            org.junit.jupiter
-            junit-jupiter
-            test
-        
         
             commons-validator
             commons-validator
             ${validator.version}
         
+        
+            org.apache.commons
+            commons-lang3
+            ${apache-commons-lang3.version}
+        
     
 
     
@@ -61,9 +49,9 @@
     
 
     
-        3.6.1
-        28.1-jre
+        11
+        11
         1.7
+        3.12.0
     
-
-
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/isuppercase/StringFirstCharacterUppercaseUnitTest.java b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/isuppercase/StringFirstCharacterUppercaseUnitTest.java
new file mode 100644
index 0000000000..524f7ca839
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/isuppercase/StringFirstCharacterUppercaseUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.isuppercase;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import com.google.common.base.Ascii;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class StringFirstCharacterUppercaseUnitTest {
+
+    @Test
+    public void givenString_whenCheckingWithCharacterIsUpperCase_thenStringCapitalized() {
+        String example = "Katie";
+        Assertions.assertTrue(Character.isUpperCase(example.charAt(0)));
+    }
+
+    @Test
+    public void givenString_whenCheckingWithRegex_thenStringCapitalized() {
+        String example = "Katie";
+        String regEx = "[A-Z]\\w*";
+
+        Assertions.assertTrue(example.matches(regEx));
+    }
+
+    @Test
+    public void givenString_whenCheckingWithGuava_thenStringCapitalized() {
+        String example = "Katie";
+        Assertions.assertTrue(Ascii.isUpperCase(example.charAt(0)));
+    }
+}
diff --git a/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/repeatedcharstring/RepeatedCharacterStringUnitTest.java b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/repeatedcharstring/RepeatedCharacterStringUnitTest.java
new file mode 100644
index 0000000000..81e78e8fd0
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/repeatedcharstring/RepeatedCharacterStringUnitTest.java
@@ -0,0 +1,104 @@
+package com.baeldung.repeatedcharstring;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+
+import static java.util.stream.Stream.generate;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RepeatedCharacterStringUnitTest {
+
+    private static final String EXPECTED_STRING = "aaaaaaa";
+    private static final int N = 7;
+
+    @Test
+    void givenSingleCharacterString_whenRepeat_thenStringCreated() {
+        String newString = "a".repeat(N);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenMultiCharacterString_whenRepeat_thenStringCreated() {
+        String newString = "-->".repeat(5);
+        assertEquals("-->-->-->-->-->", newString);
+    }
+
+    @Test
+    void givenString_whenStringBuilderUsed_thenStringCreated() {
+        StringBuilder builder = new StringBuilder(N);
+        for (int i = 0; i < N; i++) {
+            builder.append("a");
+        }
+        String newString = builder.toString();
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenCharArrayUsed_thenStringCreated() {
+        char[] charArray = new char[N];
+        for (int i = 0; i < N; i++) {
+            charArray[i] = 'a';
+        }
+        String newString = new String(charArray);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenApacheStringUtilsUsed_thenStringCreated() {
+        char charToAppend = 'a';
+        String newString = StringUtils.repeat(charToAppend, N);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenGuavaRepeatUsed_thenStringCreated() {
+        String charToAppend = "a";
+        String newString = Strings.repeat(charToAppend, N);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenArraysFillUsed_thenStringCreated() {
+        char charToAppend = 'a';
+        char[] charArray = new char[N];
+        Arrays.fill(charArray, charToAppend);
+        String newString = new String(charArray);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenGenerateAndJoiningUsed_thenStringCreated() {
+        String charToAppend = "a";
+        String newString = generate(() -> charToAppend).limit(N).collect(Collectors.joining());
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenStringJoinUsed_thenStringCreated() {
+        String charToAppend = "a";
+        String newString = String.join("", Collections.nCopies(N, charToAppend));
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenGuavaJoinerUsed_thenStringCreated() {
+        String charToAppend = "a";
+        String newString = Joiner.on("").join(Collections.nCopies(N, charToAppend));
+        assertEquals(EXPECTED_STRING, newString);
+    }
+
+    @Test
+    void givenString_whenRandomStringUtilsUsed_thenStringCreated() {
+        String charToAppend = "a";
+        String newString = RandomStringUtils.random(N, charToAppend);
+        assertEquals(EXPECTED_STRING, newString);
+    }
+}
diff --git a/core-java-modules/core-java-string-algorithms/pom.xml b/core-java-modules/core-java-string-algorithms/pom.xml
index 9fea569b29..84f3b61f84 100644
--- a/core-java-modules/core-java-string-algorithms/pom.xml
+++ b/core-java-modules/core-java-string-algorithms/pom.xml
@@ -15,11 +15,6 @@
     
 
     
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.apache.commons
             commons-lang3
@@ -45,12 +40,6 @@
             emoji-java
             ${emoji-java.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -64,9 +53,7 @@
     
 
     
-        27.0.1-jre
         0.4.0
-        3.6.1
         4.0.0
     
 
diff --git a/core-java-modules/core-java-string-conversions-2/README.md b/core-java-modules/core-java-string-conversions-2/README.md
index 46eb783a27..7abcd5e97a 100644
--- a/core-java-modules/core-java-string-conversions-2/README.md
+++ b/core-java-modules/core-java-string-conversions-2/README.md
@@ -9,4 +9,6 @@ This module contains articles about string conversions from/to another type.
 - [Converting String to BigDecimal in Java](https://www.baeldung.com/java-string-to-bigdecimal)
 - [Converting String to BigInteger in Java](https://www.baeldung.com/java-string-to-biginteger)
 - [Convert a String to Camel Case](https://www.baeldung.com/java-string-to-camel-case)
+- [Convert a ByteBuffer to String in Java](https://www.baeldung.com/java-bytebuffer-to-string)
+- [Convert String to Float and Back in Java](https://www.baeldung.com/java-string-to-float)
 - More articles: [[<-- prev]](/core-java-string-conversions)
diff --git a/core-java-modules/core-java-string-conversions-2/pom.xml b/core-java-modules/core-java-string-conversions-2/pom.xml
index ff4955726b..e424ef3083 100644
--- a/core-java-modules/core-java-string-conversions-2/pom.xml
+++ b/core-java-modules/core-java-string-conversions-2/pom.xml
@@ -15,22 +15,6 @@
     
 
     
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
-        
-            org.junit.vintage
-            junit-vintage-engine
-            test
-        
-        
-            org.hamcrest
-            hamcrest
-            ${hamcrest.version}
-            test
-        
         
             com.ibm.icu
             icu4j
@@ -46,21 +30,8 @@
             commons-text
             ${commons-text.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
-    
-        64.2
-        3.12.2
-        1.9
-        30.1.1-jre
-    
-
     
         core-java-string-conversions-2
         
@@ -71,4 +42,9 @@
         
     
 
+    
+        64.2
+        1.9
+    
+
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/bytebuffertostring/ByteArrayToStringUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/bytebuffertostring/ByteArrayToStringUnitTest.java
new file mode 100644
index 0000000000..c498921d9a
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/bytebuffertostring/ByteArrayToStringUnitTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.bytebuffertostring;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+
+public class ByteArrayToStringUnitTest {
+    private static Charset charset = StandardCharsets.UTF_8;
+    private static final String content = "baeldung";
+
+    @Test
+    public void convertUsingNewStringFromBufferArray_thenOK() {
+        // Allocate a ByteBuffer
+        ByteBuffer byteBuffer = ByteBuffer.wrap(content.getBytes());
+        if (byteBuffer.hasArray()) {
+            String newContent = new String(byteBuffer.array(), charset);
+            assertEquals(content, newContent);
+        }
+    }
+
+    @Test
+    public void convertUsingNewStringFromByteBufferGetBytes_thenOK() {
+        // Allocate a ByteBuffer
+        ByteBuffer byteBuffer = ByteBuffer.wrap(content.getBytes());
+        byte[] bytes = new byte[byteBuffer.remaining()];
+        byteBuffer.get(bytes);
+        String newContent = new String(bytes, charset);
+        assertEquals(content, newContent);
+    }
+
+    @Test
+    public void convertUsingCharsetDecode_thenOK() {
+        // Allocate a ByteBuffer
+        ByteBuffer byteBuffer = ByteBuffer.wrap(content.getBytes());
+        String newContent = charset.decode(byteBuffer)
+            .toString();
+        assertEquals(content, newContent);
+    }
+
+}
diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtofloat/StringToFloatConversionUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtofloat/StringToFloatConversionUnitTest.java
new file mode 100644
index 0000000000..5780946bca
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtofloat/StringToFloatConversionUnitTest.java
@@ -0,0 +1,187 @@
+package com.baeldung.stringtofloat;
+
+import org.junit.jupiter.api.Test;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.ParseException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class StringToFloatConversionUnitTest {
+
+    @Test
+    public void givenFloat_whenStringConcatenation_thenReturnString() {
+        Float givenFloat = 1.25f;
+
+        String result = givenFloat + "";
+
+        assertEquals("1.25", result);
+    }
+
+    @Test
+    public void givenFloatPrimitive_whenStringConcatenation_thenReturnString() {
+        float givenFloat = 1.25f;
+
+        String result = givenFloat + "";
+
+        assertEquals("1.25", result);
+    }
+
+    @Test
+    public void givenNullFloat_whenStringConcatenation_thenReturnNullString() {
+        Float givenFloat = null;
+
+        String result = givenFloat + "";
+
+        assertEquals("null", result);
+    }
+
+    @Test
+    public void givenFloat_whenToString_thenReturnString() {
+        Float givenFloat = 1.25f;
+
+        String result = Float.toString(givenFloat);
+
+        assertEquals("1.25", result);
+    }
+
+    @Test
+    public void givenNullFloat_whenToString_thenThrowNullPointerException() {
+        Float givenFloat = null;
+
+        assertThrows(NullPointerException.class, () -> Float.toString(givenFloat));
+    }
+
+    @Test
+    public void givenFloat_whenValueOf_thenReturnString() {
+        Float givenFloat = 1.25f;
+
+        String result = String.valueOf(givenFloat);
+
+        assertEquals("1.25", result);
+    }
+
+    @Test
+    public void givenNullFloat_whenValueOf_thenReturnNullString() {
+        Float givenFloat = null;
+
+        String result = String.valueOf(givenFloat);
+
+        assertEquals("null", result);
+    }
+
+    @Test
+    public void givenFloat_whenDecimalFormat_thenReturnString() {
+        Float givenFloat = 1.25f;
+
+        String result = new DecimalFormat("#.0000").format(givenFloat);
+
+        assertEquals("1.2500", result);
+    }
+
+    @Test
+    public void givenFloat_whenDecimalFormat_thenReturnWholeNumberString() {
+        Float givenFloat = 1.0025f;
+
+        String result = new DecimalFormat("#.##").format(givenFloat);
+
+        assertEquals("1", result);
+    }
+
+    @Test
+    public void givenNullFloat_whenDecimalFormat_thenThrowIllegalArgumentException() {
+        Float givenFloat = null;
+
+        assertThrows(IllegalArgumentException.class, () -> new DecimalFormat("#.000").format(givenFloat));
+    }
+
+    @Test
+    public void givenFloat_whenStringFormat_thenReturnString() {
+        Float givenFloat = 1.25f;
+
+        String result = String.format("%f", givenFloat);
+
+        assertEquals("1.250000", result);
+    }
+
+    @Test
+    public void givenFloat_whenStringFormatWithDecimalLimit_thenReturnRoundedString() {
+        Float givenFloat = 1.256f;
+
+        String result = String.format("%.2f", givenFloat);
+
+        assertEquals("1.26", result);
+    }
+
+    @Test
+    public void givenNullFloat_whenStringFormatWithDecimalLimit_thenReturnNullString() {
+        Float givenFloat = null;
+
+        String result = String.format("%f", givenFloat);
+
+        assertEquals("null", result);
+    }
+
+    @Test
+    public void givenString_whenParseFloat_thenReturnFloat() {
+        String givenString = "1.25";
+
+        float result = Float.parseFloat(givenString);
+
+        assertEquals(1.25f, result);
+    }
+
+    @Test
+    public void givenNullString_whenParseFloat_thenThrowNullPointerException() {
+        String givenString = null;
+
+        assertThrows(NullPointerException.class, () -> Float.parseFloat(givenString));
+    }
+
+    @Test
+    public void givenNonParsableString_whenParseFloat_thenThrowNumberFormatException() {
+        String givenString = "1.23x";
+
+        assertThrows(NumberFormatException.class, () -> Float.parseFloat(givenString));
+    }
+
+    @Test
+    public void givenString_whenValueOf_thenReturnFloat() {
+        String givenString = "1.25";
+
+        Float result = Float.valueOf(givenString);
+
+        assertEquals(1.25f, result);
+    }
+
+    @Test
+    public void givenNonParsableString_whenValueOf_thenThrowNumberFormatException() {
+        String givenString = "1.25x";
+
+        assertThrows(NumberFormatException.class, () -> Float.valueOf(givenString));
+    }
+
+    @Test
+    public void givenString_whenConstructor_thenReturnFloat() {
+        String givenString = "1.25";
+
+        Float result = new Float(givenString);
+
+        assertEquals(1.25f, result);
+    }
+
+    @Test
+    public void givenString_whenDecimalFormat_thenReturnFloat() throws ParseException {
+        String givenString = "1,250";
+        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
+        symbols.setDecimalSeparator(',');
+        DecimalFormat decimalFormat = new DecimalFormat("#.000");
+        decimalFormat.setDecimalFormatSymbols(symbols);
+
+        Float result = decimalFormat.parse(givenString).floatValue();
+
+        assertEquals(1.25f, result);
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-conversions/README.md b/core-java-modules/core-java-string-conversions/README.md
index 849660e482..a86062e4d4 100644
--- a/core-java-modules/core-java-string-conversions/README.md
+++ b/core-java-modules/core-java-string-conversions/README.md
@@ -10,7 +10,7 @@ This module contains articles about string conversions from/to another type.
 - [Converting a Stack Trace to a String in Java](https://www.baeldung.com/java-stacktrace-to-string)
 - [Image to Base64 String Conversion](https://www.baeldung.com/java-base64-image-string)
 - [Convert a Comma Separated String to a List in Java](https://www.baeldung.com/java-string-with-separator-to-list)
-- [Converting Java String to Double](https://www.baeldung.com/java-string-to-double)
+- [Convert String to Double in Java](https://www.baeldung.com/java-string-to-double)
 - [Convert Char to String in Java](https://www.baeldung.com/java-convert-char-to-string)
 - [Convert String to int or Integer in Java](https://www.baeldung.com/java-convert-string-to-int-or-integer)
-- More articles: [[next -->]](/core-java-string-conversions-2)
\ No newline at end of file
+- More articles: [[next -->]](/core-java-string-conversions-2)
diff --git a/core-java-modules/core-java-string-conversions/pom.xml b/core-java-modules/core-java-string-conversions/pom.xml
index 1047e3e7c3..f10ae401b3 100644
--- a/core-java-modules/core-java-string-conversions/pom.xml
+++ b/core-java-modules/core-java-string-conversions/pom.xml
@@ -30,24 +30,6 @@
             commons-lang3
             ${commons-lang3.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
-        
-            org.hamcrest
-            hamcrest
-            ${hamcrest.version}
-            test
-        
     
 
     
@@ -62,7 +44,6 @@
 
     
         61.1
-        3.6.1
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-operations-2/README.md b/core-java-modules/core-java-string-operations-2/README.md
index d66515d372..f95b002906 100644
--- a/core-java-modules/core-java-string-operations-2/README.md
+++ b/core-java-modules/core-java-string-operations-2/README.md
@@ -12,5 +12,5 @@ This module contains articles about string operations.
 - [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives)
 - [Encode a String to UTF-8 in Java](https://www.baeldung.com/java-string-encode-utf-8)
 - [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding)
-- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) #remove additional readme file
+- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii)
 - More articles: [[<-- prev]](../core-java-string-operations)
diff --git a/core-java-modules/core-java-string-operations-2/pom.xml b/core-java-modules/core-java-string-operations-2/pom.xml
index db8f78da70..92bfa6b2d8 100644
--- a/core-java-modules/core-java-string-operations-2/pom.xml
+++ b/core-java-modules/core-java-string-operations-2/pom.xml
@@ -20,11 +20,6 @@
             validation-api
             ${validation-api.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
         
             org.apache.commons
             commons-lang3
@@ -45,12 +40,6 @@
             javax.el
             ${javax.el.version}
         
-        
-            org.hamcrest
-            hamcrest
-            ${hamcrest.version}
-            test
-        
         
             org.openjdk.jmh
             jmh-core
@@ -66,12 +55,6 @@
             commons-codec
             ${commons-codec.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -108,9 +91,7 @@
     
 
     
-        3.6.1
         2.0.0.Final
-        28.2-jre
         6.0.2.Final
         3.0.0
         2.2.6
diff --git a/guest/webservices/soap_example/src/main/resources/logback.xml b/core-java-modules/core-java-string-operations-2/src/main/resources/logback.xml
similarity index 100%
rename from guest/webservices/soap_example/src/main/resources/logback.xml
rename to core-java-modules/core-java-string-operations-2/src/main/resources/logback.xml
diff --git a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/README.md b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/README.md
deleted file mode 100644
index c6d5826333..0000000000
--- a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-### Relevant Articles:
-- [Convert Hex to ASCII in Java](http://www.baeldung.com/java-convert-hex-to-ascii)
diff --git a/core-java-modules/core-java-string-operations-3/README.md b/core-java-modules/core-java-string-operations-3/README.md
index 1a131c57ac..b22cf56e3a 100644
--- a/core-java-modules/core-java-string-operations-3/README.md
+++ b/core-java-modules/core-java-string-operations-3/README.md
@@ -7,3 +7,6 @@
 - [Validate String as Filename in Java](https://www.baeldung.com/java-validate-filename)
 - [Count Spaces in a Java String](https://www.baeldung.com/java-string-count-spaces)
 - [Remove Accents and Diacritics From a String in Java](https://www.baeldung.com/java-remove-accents-from-text)
+- [Remove Beginning and Ending Double Quotes from a String](https://www.baeldung.com/java-remove-start-end-double-quote)
+- [Splitting a Java String by Multiple Delimiters](https://www.baeldung.com/java-string-split-multiple-delimiters)
+- [Split a String Only on the First Occurrence of Delimiter](https://www.baeldung.com/java-split-string-first-delimiter)
diff --git a/core-java-modules/core-java-string-operations-3/pom.xml b/core-java-modules/core-java-string-operations-3/pom.xml
index 20e9bcb39a..19b3d57ffd 100644
--- a/core-java-modules/core-java-string-operations-3/pom.xml
+++ b/core-java-modules/core-java-string-operations-3/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -26,12 +25,6 @@
             commons-lang3
             ${apache-commons-lang3.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             org.apache.maven
             maven-artifact
@@ -52,11 +45,6 @@
             semver4j
             ${semver4j.version}
         
-        
-            com.google.guava
-            guava
-            ${guava.version}
-        
     
 
     
@@ -82,14 +70,12 @@
     
         11
         11
-        3.6.1
         5.3.9
         3.12.0
-        31.0.1-jre
         3.6.3
         6.1.1
         2.11.1
         3.1.0
     
 
-
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/firstword/FirstWordGetter.java b/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/firstword/FirstWordGetter.java
new file mode 100644
index 0000000000..03c134752a
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/firstword/FirstWordGetter.java
@@ -0,0 +1,20 @@
+package com.baeldung.firstword;
+
+public class FirstWordGetter {
+
+    public static void main(String[] args) {
+        String input = "Roberto \"I wish you a bug-free day\"";
+        System.out.println("Using split: " + getFirstWordUsingSplit(input));
+        System.out.println("Using subString: " + getFirstWordUsingSubString(input));
+    }
+
+    public static String getFirstWordUsingSubString(String input) {
+        int index = input.contains(" ") ? input.indexOf(" ") : 0;
+        return input.substring(0, index);
+    }
+
+    public static String getFirstWordUsingSplit(String input) {
+        String[] tokens = input.split(" ", 2);
+        return tokens[0];
+    }
+}
diff --git a/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/firstword/FirstWordGetterUnitTest.java b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/firstword/FirstWordGetterUnitTest.java
new file mode 100644
index 0000000000..bdaa25180e
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/firstword/FirstWordGetterUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.firstword;
+
+import static com.baeldung.firstword.FirstWordGetter.getFirstWordUsingSplit;
+import static com.baeldung.firstword.FirstWordGetter.getFirstWordUsingSubString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class FirstWordGetterUnitTest {
+
+    @Test
+    public void givenString_whenSplit_thenFirstWordIsReturned() {
+        assertEquals("Roberto", getFirstWordUsingSplit("Roberto \"I wish you a bug-free day\""));
+    }
+
+    @Test
+    public void givenStringWithNoSpace_whenSplit_thenFirstWordIsReturned() {
+        assertEquals("StringWithNoSpace", getFirstWordUsingSplit("StringWithNoSpace"));
+    }
+
+    @Test
+    public void givenString_whenPassedToSubstring_thenFirstWordIsReturned() {
+        assertEquals("Roberto", getFirstWordUsingSubString("Roberto \"I wish you a bug-free day\""));
+    }
+
+    @Test
+    public void givenStringWithNoSpace_whenPassedToSubstring_thenFirstWordIsReturned() {
+        assertEquals("", getFirstWordUsingSubString("StringWithNoSpace"));
+    }
+}
diff --git a/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/multipledelimiterssplit/MultipleDelimitersSplitUnitTest.java b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/multipledelimiterssplit/MultipleDelimitersSplitUnitTest.java
index c8f8fc2d98..2da8955645 100644
--- a/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/multipledelimiterssplit/MultipleDelimitersSplitUnitTest.java
+++ b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/multipledelimiterssplit/MultipleDelimitersSplitUnitTest.java
@@ -17,7 +17,7 @@ public class MultipleDelimitersSplitUnitTest {
     @Test
     public void givenString_whenSplittingByMultipleDelimitersWithRegEx_thenStringSplit() {
         String example = "Mary;Thomas:Jane-Kate";
-        String[] names = example.split(";|:|-");
+        String[] names = example.split("[;:-]");
         String[] expectedNames = new String[]{"Mary", "Thomas", "Jane", "Kate"};
         Assertions.assertEquals(4, names.length);
         Assertions.assertArrayEquals(expectedNames, names);
@@ -38,7 +38,7 @@ public class MultipleDelimitersSplitUnitTest {
         String example = "Mary;Thomas:Jane-Kate";
         String[] expectedArray = new String[]{"Mary", "Thomas", "Jane", "Kate"};
         Iterable expected = Arrays.asList(expectedArray);
-        Iterable names = Splitter.on(Pattern.compile(";|:|-")).split(example);
+        Iterable names = Splitter.on(Pattern.compile("[;:-]")).split(example);
         Assertions.assertEquals(4, Iterators.size(names.iterator()));
         Assertions.assertIterableEquals(expected, names);
     }
@@ -48,7 +48,7 @@ public class MultipleDelimitersSplitUnitTest {
         String example = "Mary;Thomas:Jane-Kate";
         String[] expectedArray = new String[]{"Mary", "Thomas", "Jane", "Kate"};
         Iterable expected = Arrays.asList(expectedArray);
-        Iterable names = Splitter.onPattern(";|:|-").split(example);
+        Iterable names = Splitter.onPattern("[;:-]").split(example);
         Assertions.assertEquals(4, Iterators.size(names.iterator()));
         Assertions.assertIterableEquals(expected, names);
     }
diff --git a/core-java-modules/core-java-string-operations-4/README.md b/core-java-modules/core-java-string-operations-4/README.md
new file mode 100644
index 0000000000..0e6c9e7e2c
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/README.md
@@ -0,0 +1,9 @@
+### Relevant Articles:
+
+- [Ignoring Commas in Quotes When Splitting a Comma-separated String](https://www.baeldung.com/java-split-string-commas)
+- [Compare Strings While Ignoring Whitespace in Java](https://www.baeldung.com/java-compare-string-whitespace)
+- [Concatenating Null Strings in Java](https://www.baeldung.com/java-concat-null-string)
+- [Split a String Every n Characters in Java](https://www.baeldung.com/java-string-split-every-n-characters)
+- [String equals() Vs contentEquals() in Java](https://www.baeldung.com/java-string-equals-vs-contentequals)
+- [Check if a String Ends with a Certain Pattern in Java](https://www.baeldung.com/java-string-ends-pattern)
+
diff --git a/core-java-modules/core-java-string-operations-4/pom.xml b/core-java-modules/core-java-string-operations-4/pom.xml
new file mode 100644
index 0000000000..7f71ea8da5
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/pom.xml
@@ -0,0 +1,56 @@
+
+
+    4.0.0
+    core-java-string-operations-4
+    0.1.0-SNAPSHOT
+    core-java-string-operations-4
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        
+            com.opencsv
+            opencsv
+            ${opencsv.version}
+        
+        
+            org.springframework
+            spring-core
+            ${spring-core.version}
+        
+        
+            org.apache.commons
+            commons-lang3
+            ${apache-commons-lang3.version}
+        
+    
+
+    
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                
+                    ${maven.compiler.source}
+                    ${maven.compiler.target}
+                
+            
+        
+    
+
+    
+        11
+        11
+        4.1
+        5.3.13
+        3.12.0
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedString.java b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedString.java
new file mode 100644
index 0000000000..c3bbdb4dfb
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedString.java
@@ -0,0 +1,66 @@
+package com.baeldung.commaseparatedstring;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Splitter;
+import com.opencsv.CSVParser;
+import com.opencsv.CSVParserBuilder;
+import com.opencsv.CSVReader;
+import com.opencsv.CSVReaderBuilder;
+
+public class SplitCommaSeparatedString {
+
+    public static List splitWithParser(String input) {
+
+        List tokens = new ArrayList();
+        int startPosition = 0;
+        boolean isInQuotes = false;
+        for (int currentPosition = 0; currentPosition < input.length(); currentPosition++) {
+            if (input.charAt(currentPosition) == '\"') {
+                isInQuotes = !isInQuotes;
+            } else if (input.charAt(currentPosition) == ',' && !isInQuotes) {
+                tokens.add(input.substring(startPosition, currentPosition));
+                startPosition = currentPosition + 1;
+            }
+        }
+
+        String lastToken = input.substring(startPosition);
+        if (lastToken.equals(",")) {
+            tokens.add("");
+        } else {
+            tokens.add(lastToken);
+        }
+
+        return tokens;
+    }
+
+    public static List splitWithRegex(String input) {
+        String[] tokens = input.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
+        return Arrays.asList(tokens);
+    }
+
+    public static List splitWithGuava(String input) {
+        Pattern pattern = Pattern.compile(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
+        Splitter splitter = Splitter.on(pattern);
+        return splitter.splitToList(input);
+    }
+
+    public static List splitMultiLineWithOpenCSV(String input) throws IOException {
+        CSVParser parser = new CSVParserBuilder().withSeparator(',')
+            .build();
+
+        CSVReader reader = new CSVReaderBuilder(new StringReader(input)).withCSVParser(parser)
+            .build();
+
+        List list = new ArrayList<>();
+        list = reader.readAll();
+        reader.close();
+
+        return list;
+    }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/concatenation/ConcatenatingNull.java b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/concatenation/ConcatenatingNull.java
new file mode 100644
index 0000000000..250a0d6b25
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/concatenation/ConcatenatingNull.java
@@ -0,0 +1,86 @@
+package com.baeldung.concatenation;
+
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ConcatenatingNull {
+
+    public static void main(String[] args) {
+        String[] values = { "Java ", null, "", "is ", "great!" };
+
+        concatenateUsingPlusOperator(values);
+        concatenateUsingHelperMethod(values);
+        concatenateUsingStringBuilder(values);
+        concatenateUsingJoin(values);
+        concatenateUsingStringJoiner(values);
+        concatenateUsingCollectorsJoining(values);
+        concatenateUsingStringConcat(values);
+    }
+
+    public static String concatenateUsingStringConcat(String[] values) {
+        String result = "";
+
+        for (String value : values) {
+            result = result.concat(getNonNullString(value));
+        }
+
+        return result;
+    }
+
+    public static String concatenateUsingCollectorsJoining(String[] values) {
+        String result = Stream.of(values).filter(value -> null != value).collect(Collectors.joining(""));
+
+        return result;
+    }
+
+    public static String concatenateUsingStringJoiner(String[] values) {
+        StringJoiner result = new StringJoiner("");
+
+        for (String value : values) {
+            result = result.add(getNonNullString(value));
+        }
+
+        return result.toString();
+    }
+
+    public static String concatenateUsingJoin(String[] values) {
+        String result = String.join("", values);
+
+        return result;
+    }
+
+    public static String concatenateUsingStringBuilder(String[] values) {
+        StringBuilder result = new StringBuilder();
+
+        for (String value : values) {
+            result = result.append(getNonNullString(value));
+        }
+
+        return result.toString();
+    }
+
+    public static String concatenateUsingHelperMethod(String[] values) {
+        String result = "";
+
+        for (String value : values) {
+            result = result + getNonNullString(value);
+        }
+
+        return result;
+    }
+
+    public static String concatenateUsingPlusOperator(String[] values) {
+        String result = "";
+
+        for (String value : values) {
+            result = result + (value == null ? "" : value);
+        }
+
+        return result;
+    }
+
+    private static String getNonNullString(String value) {
+        return value == null ? "" : value;
+    }
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/endswithpattern/StringEndsWithPattern.java b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/endswithpattern/StringEndsWithPattern.java
new file mode 100644
index 0000000000..345ad6d91f
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/endswithpattern/StringEndsWithPattern.java
@@ -0,0 +1,45 @@
+package com.baeldung.endswithpattern;
+
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class StringEndsWithPattern {
+
+    public static boolean usingStringEndsWithMethod(String text, String suffix) {
+        if (text == null || suffix == null) {
+            return false;
+        }
+        return text.endsWith(suffix);
+    }
+
+    public static boolean usingStringMatchesMethod(String text, String suffix) {
+        if (text == null || suffix == null) {
+            return false;
+        }
+        String regex = ".*" + suffix + "$";
+        return text.matches(regex);
+    }
+
+    public static boolean usingStringRegionMatchesMethod(String text, String suffix) {
+        if (text == null || suffix == null) {
+            return false;
+        }
+        int toffset = text.length() - suffix.length();
+        return text.regionMatches(toffset, suffix, 0, suffix.length());
+    }
+
+    public static boolean usingPatternClass(String text, String suffix) {
+        if (text == null || suffix == null) {
+            return false;
+        }
+        Pattern pattern = Pattern.compile(".*" + suffix + "$");
+        return pattern.matcher(text)
+            .find();
+    }
+
+    public static boolean usingApacheCommonsLang(String text, String suffix) {
+        return StringUtils.endsWith(text, suffix);
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/split/SplitStringEveryNthChar.java b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/split/SplitStringEveryNthChar.java
new file mode 100644
index 0000000000..3ac31d012a
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/split/SplitStringEveryNthChar.java
@@ -0,0 +1,51 @@
+package com.baeldung.split;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
+public class SplitStringEveryNthChar {
+
+    public static List usingSplitMethod(String text, int n) {
+        String[] results = text.split("(?<=\\G.{" + n + "})");
+
+        return Arrays.asList(results);
+    }
+
+    public static List usingSubstringMethod(String text, int n) {
+        List results = new ArrayList<>();
+        int length = text.length();
+
+        for (int i = 0; i < length; i += n) {
+            results.add(text.substring(i, Math.min(length, i + n)));
+        }
+
+        return results;
+    }
+
+    public static List usingPattern(String text, int n) {
+        List results = new ArrayList<>();
+
+        Pattern pattern = Pattern.compile(".{1," + n + "}");
+        Matcher matcher = pattern.matcher(text);
+        while (matcher.find()) {
+            String match = text.substring(matcher.start(), matcher.end());
+            results.add(match);
+        }
+
+        return results;
+    }
+
+    public static List usingGuava(String text, int n) {
+        Iterable parts = Splitter.fixedLength(n)
+            .split(text);
+
+        return ImmutableList.copyOf(parts);
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedStringUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedStringUnitTest.java
new file mode 100644
index 0000000000..ca34430099
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/commaseparatedstring/SplitCommaSeparatedStringUnitTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.commaseparatedstring;
+
+import static com.baeldung.commaseparatedstring.SplitCommaSeparatedString.splitMultiLineWithOpenCSV;
+import static com.baeldung.commaseparatedstring.SplitCommaSeparatedString.splitWithGuava;
+import static com.baeldung.commaseparatedstring.SplitCommaSeparatedString.splitWithParser;
+import static com.baeldung.commaseparatedstring.SplitCommaSeparatedString.splitWithRegex;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+
+public class SplitCommaSeparatedStringUnitTest {
+    
+    @Test
+    public void givenSingleLineInput_whenParsing_shouldIgnoreCommasInsideDoubleQuotes() {
+        String input = "baeldung,tutorial,splitting,text,\"ignoring this comma,\"";
+
+        var matcher = contains("baeldung", "tutorial", "splitting", "text", "\"ignoring this comma,\"");
+        assertThat(splitWithParser(input), matcher);
+        assertThat(splitWithRegex(input), matcher);
+        assertThat(splitWithGuava(input), matcher);
+    }
+    
+    @Test
+    public void givenMultiLineInput_whenParsing_shouldIgnoreCommasInsideDoubleQuotes() throws IOException {
+        String input = "baeldung,tutorial,splitting,text,\"ignoring this comma,\"" + System.lineSeparator()
+        + "splitting,a,regular,line,no double quotes";
+
+        String[] firstLine = new String[]{"baeldung", "tutorial", "splitting", "text", "ignoring this comma,"};
+        String[] secondLine = new String[]{"splitting", "a", "regular", "line", "no double quotes"};
+        
+        List result = splitMultiLineWithOpenCSV(input);
+        
+        assertThat(result, hasSize(2));
+        assertArrayEquals(firstLine, result.get(0));
+        assertArrayEquals(secondLine, result.get(1));
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/comparestrings/CompareIgnoreSpacesUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/comparestrings/CompareIgnoreSpacesUnitTest.java
new file mode 100644
index 0000000000..570ceb1598
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/comparestrings/CompareIgnoreSpacesUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.comparestrings;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CompareIgnoreSpacesUnitTest {
+
+    private static String normalString = "ABCDEF";
+    private static String stringWithSpaces = " AB  CD EF ";
+
+    @Test
+    public void givenTwoStrings_thenCompareWithReplaceAllMethod() {
+        assertEquals(normalString.replaceAll("\\s+",""), stringWithSpaces.replaceAll("\\s+",""));
+    }
+
+    @Test
+    public void givenTwoStrings_thenCompareWithApacheStringUtils() {
+        assertEquals(StringUtils.deleteWhitespace(normalString), StringUtils.deleteWhitespace(stringWithSpaces));
+    }
+
+    @Test
+    public void givenTwoStrings_thenCompareWithSpringStringUtils() {
+        assertEquals(org.springframework.util.StringUtils.trimAllWhitespace(normalString), org.springframework.util.StringUtils.trimAllWhitespace(stringWithSpaces));
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/concatenation/ConcatenatingNullUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/concatenation/ConcatenatingNullUnitTest.java
new file mode 100644
index 0000000000..20e5f6ad7d
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/concatenation/ConcatenatingNullUnitTest.java
@@ -0,0 +1,59 @@
+package com.baeldung.concatenation;
+
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingCollectorsJoining;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingHelperMethod;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingJoin;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingPlusOperator;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingStringBuilder;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingStringConcat;
+import static com.baeldung.concatenation.ConcatenatingNull.concatenateUsingStringJoiner;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class ConcatenatingNullUnitTest {
+
+    String[] values = { "Java ", null, "", "is ", "great!" };
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingPlus_thenNullIsIgnored() {
+        String result = concatenateUsingPlusOperator(values);
+        assertEquals("Java is great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingHelperMethod_thenNullIsIgnored() {
+        String result = concatenateUsingHelperMethod(values);
+        assertEquals("Java is great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingStringBuilder_thenNullIsIgnored() {
+        String result = concatenateUsingStringBuilder(values);
+        assertEquals("Java is great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingJoin_thenNullIsNotIgnored() {
+        String result = concatenateUsingJoin(values);
+        assertEquals("Java nullis great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingStringJoiner_thenNullIsIgnored() {
+        String result = concatenateUsingStringJoiner(values);
+        assertEquals("Java is great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingCollectorsJoining_thenNullIsIgnored() {
+        String result = concatenateUsingCollectorsJoining(values);
+        assertEquals("Java is great!", result);
+    }
+
+    @Test
+    public void givenStringElementsWithNull_whenConcatenatedUsingStringConcat_thenNullIsIgnored() {
+        String result = concatenateUsingStringConcat(values);
+        assertEquals("Java is great!", result);
+    }
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/endswithpattern/StringEndsWithPatternUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/endswithpattern/StringEndsWithPatternUnitTest.java
new file mode 100644
index 0000000000..1680df17df
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/endswithpattern/StringEndsWithPatternUnitTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.endswithpattern;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+public class StringEndsWithPatternUnitTest {
+
+    private static final String TEXT = "Welcome to baeldung.com";
+    private static final String SUFFIX = "com";
+
+    @Test
+    public void givenStringAndSuffix_whenUsingStringEndsWith_thenCheck() {
+
+        assertTrue(StringEndsWithPattern.usingStringEndsWithMethod(TEXT, SUFFIX));
+    }
+
+    @Test
+    public void givenStringAndSuffix_whenUsingStringMatches_thenCheck() {
+
+        assertTrue(StringEndsWithPattern.usingStringMatchesMethod(TEXT, SUFFIX));
+    }
+
+    @Test
+    public void givenStringAndSuffix_whenUsingStringRegionMatches_thenCheck() {
+
+        assertTrue(StringEndsWithPattern.usingStringRegionMatchesMethod(TEXT, SUFFIX));
+    }
+
+    @Test
+    public void givenStringAndSuffix_whenUsingPatternClass_thenCheck() {
+
+        assertTrue(StringEndsWithPattern.usingPatternClass(TEXT, SUFFIX));
+    }
+
+    @Test
+    public void givenStringAndSuffix_whenUsingApacheCommonsLang_thenCheck() {
+        
+        assertTrue(StringEndsWithPattern.usingApacheCommonsLang(TEXT, SUFFIX));
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/equalsvscontentequals/StringEqualsVsContentEqualsUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/equalsvscontentequals/StringEqualsVsContentEqualsUnitTest.java
new file mode 100644
index 0000000000..1b8c97d024
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/equalsvscontentequals/StringEqualsVsContentEqualsUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.equalsvscontentequals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class StringEqualsVsContentEqualsUnitTest {
+
+    String actualString = "baeldung";
+    String identicalString = "baeldung";
+    CharSequence identicalStringInstance = "baeldung";
+    CharSequence identicalStringBufferInstance = new StringBuffer("baeldung");
+
+    @Test
+    public void whenIdenticalTestString_thenBothTrue() {
+        assertTrue(actualString.equals(identicalString));
+        assertTrue(actualString.contentEquals(identicalString));
+    }
+
+    @Test
+    public void whenSameContentButDifferentType_thenEqualsIsFalseAndContentEqualsIsTrue() {
+        assertTrue(actualString.equals(identicalStringInstance));
+        assertTrue(actualString.contentEquals(identicalStringInstance));
+
+        assertFalse(actualString.equals(identicalStringBufferInstance));
+        assertTrue(actualString.contentEquals(identicalStringBufferInstance));
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/split/SplitStringEveryNthCharUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/split/SplitStringEveryNthCharUnitTest.java
new file mode 100644
index 0000000000..03dcd5312e
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/split/SplitStringEveryNthCharUnitTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.split;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+public class SplitStringEveryNthCharUnitTest {
+
+    public static final String TEXT = "abcdefgh123456";
+
+    @Test
+    public void givenString_whenUsingSplit_thenSplit() {
+        List results = SplitStringEveryNthChar.usingSplitMethod(TEXT, 3);
+
+        assertThat(results, contains("abc", "def", "gh1", "234", "56"));
+    }
+
+    @Test
+    public void givenString_whenUsingSubstring_thenSplit() {
+        List results = SplitStringEveryNthChar.usingSubstringMethod(TEXT, 4);
+
+        assertThat(results, contains("abcd", "efgh", "1234", "56"));
+    }
+
+    @Test
+    public void givenString_whenUsingPattern_thenSplit() {
+        List results = SplitStringEveryNthChar.usingPattern(TEXT, 5);
+
+        assertThat(results, contains("abcde", "fgh12", "3456"));
+    }
+
+    @Test
+    public void givenString_whenUsingGuava_thenSplit() {
+        List results = SplitStringEveryNthChar.usingGuava(TEXT, 6);
+
+        assertThat(results, contains("abcdef", "gh1234", "56"));
+    }
+
+}
diff --git a/core-java-modules/core-java-string-operations/pom.xml b/core-java-modules/core-java-string-operations/pom.xml
index 67ce43277e..20e4df3ba3 100644
--- a/core-java-modules/core-java-string-operations/pom.xml
+++ b/core-java-modules/core-java-string-operations/pom.xml
@@ -40,12 +40,6 @@
             commons-codec
             ${commons-codec.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -59,7 +53,6 @@
     
 
     
-        3.6.1
         1.15
     
 
diff --git a/core-java-modules/core-java-strings/pom.xml b/core-java-modules/core-java-strings/pom.xml
index aca0bb3346..2cc35dad5f 100644
--- a/core-java-modules/core-java-strings/pom.xml
+++ b/core-java-modules/core-java-strings/pom.xml
@@ -12,7 +12,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -36,12 +35,6 @@
             icu4j
             ${icu4j.version}
         
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
     
 
     
@@ -55,7 +48,6 @@
     
 
     
-        3.6.1
         61.1
         15
     
diff --git a/core-java-modules/core-java-sun/pom.xml b/core-java-modules/core-java-sun/pom.xml
index 347020a736..e959932235 100644
--- a/core-java-modules/core-java-sun/pom.xml
+++ b/core-java-modules/core-java-sun/pom.xml
@@ -12,17 +12,9 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             com.sun
             tools
@@ -94,10 +86,7 @@
     
 
     
-        
-        3.6.1
         1.7.0
-        
         1.8.0
     
 
diff --git a/core-java-modules/core-java-time-measurements/pom.xml b/core-java-modules/core-java-time-measurements/pom.xml
index 663cf6708b..cb2fd9fb40 100644
--- a/core-java-modules/core-java-time-measurements/pom.xml
+++ b/core-java-modules/core-java-time-measurements/pom.xml
@@ -13,7 +13,6 @@
         com.baeldung.core-java-modules
         core-java-modules
         0.0.1-SNAPSHOT
-        ../
     
 
     
@@ -28,13 +27,6 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj.version}
-            test
-        
         
             joda-time
             joda-time
@@ -46,15 +38,9 @@
             ${asspectj.version}
         
         
-            org.powermock
-            powermock-module-junit4
-            ${powermock.version}
-            test
-        
-        
-            org.powermock
-            powermock-api-mockito2
-            ${powermock.version}
+            org.mockito
+            mockito-inline
+            ${mockito-inline.version}
             test
         
         
@@ -75,8 +61,8 @@
         
         
             
+                org.apache.maven.plugins
                 maven-surefire-plugin
-                ${maven-surefire-plugin.version}
                 
                     
                         -javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar
@@ -88,17 +74,12 @@
     
 
     
-        
         3.6.1
         2.10
-        1.18.12
-        
-        3.6.1
+        1.18.22
         1.8.9
-        2.0.7
         1.44
-        
-        2.22.1
+        4.1.0
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java
index 608199197a..ba1821b1ce 100644
--- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java
+++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java
@@ -1,20 +1,15 @@
 package com.baeldung.time;
 
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
+import org.mockito.MockedStatic;
 
 import java.time.Clock;
 import java.time.Instant;
 import java.time.ZoneId;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.when;
+import static org.mockito.Mockito.mockStatic;
 
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ Instant.class })
 public class InstantUnitTest {
 
     @Test
@@ -22,12 +17,12 @@ public class InstantUnitTest {
         String instantExpected = "2014-12-22T10:15:30Z";
         Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
         Instant instant = Instant.now(clock);
-        mockStatic(Instant.class);
-        when(Instant.now()).thenReturn(instant);
 
-        Instant now = Instant.now();
-
-        assertThat(now.toString()).isEqualTo(instantExpected);
+        try (MockedStatic mockedStatic = mockStatic(Instant.class)) {
+            mockedStatic.when(Instant::now).thenReturn(instant);
+            Instant now = Instant.now();
+            assertThat(now.toString()).isEqualTo(instantExpected);
+        }
     }
 
     @Test
diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java
index 52dc9ba1c6..e4401d67b7 100644
--- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java
+++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java
@@ -1,9 +1,6 @@
 package com.baeldung.time;
 
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
 
 import java.time.Clock;
 import java.time.Instant;
@@ -11,11 +8,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneId;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
 
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ LocalDateTime.class })
 public class LocalDateTimeUnitTest {
 
     @Test
diff --git a/core-java-modules/core-java-uuid/README.md b/core-java-modules/core-java-uuid/README.md
new file mode 100644
index 0000000000..836552d798
--- /dev/null
+++ b/core-java-modules/core-java-uuid/README.md
@@ -0,0 +1,5 @@
+## Core Java UUID
+
+### Relevant Articles: 
+- [Generating Alphanumeric UUID String in Java](https://www.baeldung.com/java-generate-alphanumeric-uuid)
+- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
diff --git a/core-java-modules/core-java-uuid/pom.xml b/core-java-modules/core-java-uuid/pom.xml
new file mode 100644
index 0000000000..28519a1a68
--- /dev/null
+++ b/core-java-modules/core-java-uuid/pom.xml
@@ -0,0 +1,147 @@
+
+
+    4.0.0
+    core-java-uuid
+    0.1.0-SNAPSHOT
+    core-java-uuid
+    jar
+
+    
+        com.baeldung.core-java-modules
+        core-java-modules
+        0.0.1-SNAPSHOT
+    
+
+    
+        
+            log4j
+            log4j
+            ${log4j.version}
+        
+         
+            org.slf4j
+            log4j-over-slf4j
+            ${org.slf4j.version}
+        
+    
+
+    
+        core-java-uuid
+        
+            
+                src/main/resources
+                true
+            
+        
+
+        
+            
+                org.apache.maven.plugins
+                maven-dependency-plugin
+                
+                    
+                        copy-dependencies
+                        prepare-package
+                        
+                            copy-dependencies
+                        
+                        
+                            ${project.build.directory}/libs
+                        
+                    
+                
+            
+            
+                org.codehaus.mojo
+                exec-maven-plugin
+                
+                    java
+                    com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
+                    
+                        -Xmx300m
+                        -XX:+UseParallelGC
+                        -classpath
+                        
+                        com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
+                    
+                
+            
+            
+                org.apache.maven.plugins
+                maven-javadoc-plugin
+                ${maven-javadoc-plugin.version}
+                
+                    ${source.version}
+                    ${target.version}
+                
+            
+        
+    
+
+    
+        
+            integration
+            
+                
+                    
+                        org.apache.maven.plugins
+                        maven-surefire-plugin
+                        
+                            
+                                integration-test
+                                
+                                    test
+                                
+                                
+                                    
+                                        **/*ManualTest.java
+                                    
+                                    
+                                        **/*IntegrationTest.java
+                                        **/*IntTest.java
+                                    
+                                
+                            
+                        
+                        
+                            
+                                json
+                            
+                        
+                    
+                    
+                        org.codehaus.mojo
+                        exec-maven-plugin
+                        
+                            
+                                run-benchmarks
+                                
+                                none
+                                
+                                    exec
+                                
+                                
+                                    test
+                                    java
+                                    
+                                        -classpath
+                                        
+                                        org.openjdk.jmh.Main
+                                        .*
+                                    
+                                
+                            
+                        
+                    
+                
+            
+        
+    
+
+    
+        3.0.0-M1
+    
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDGenerator.java
similarity index 100%
rename from core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java
rename to core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDGenerator.java
diff --git a/core-java-modules/core-java-uuid/src/main/resources/log4j.properties b/core-java-modules/core-java-uuid/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..621cf01735
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/main/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=DEBUG, A1
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/main/resources/log4j2.xml b/core-java-modules/core-java-uuid/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..a824bef9b0
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+        
+    
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java-uuid/src/main/resources/log4jstructuraldp.properties
new file mode 100644
index 0000000000..5bc2bfe4b9
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/main/resources/log4jstructuraldp.properties
@@ -0,0 +1,9 @@
+
+# Root logger 
+log4j.rootLogger=INFO, file, stdout
+
+# Write to console
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/main/resources/logback.xml b/core-java-modules/core-java-uuid/src/main/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+    
+        
+            %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/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java b/core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java
similarity index 100%
rename from core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java
rename to core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java
diff --git a/core-java-modules/core-java-uuid/src/test/resources/log4j.properties b/core-java-modules/core-java-uuid/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..621cf01735
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/test/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=DEBUG, A1
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/test/resources/log4j2.xml b/core-java-modules/core-java-uuid/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000..a824bef9b0
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/test/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+        
+    
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/test/resources/log4jstructuraldp.properties b/core-java-modules/core-java-uuid/src/test/resources/log4jstructuraldp.properties
new file mode 100644
index 0000000000..5bc2bfe4b9
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/test/resources/log4jstructuraldp.properties
@@ -0,0 +1,9 @@
+
+# Root logger 
+log4j.rootLogger=INFO, file, stdout
+
+# Write to console
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/core-java-modules/core-java-uuid/src/test/resources/logback.xml b/core-java-modules/core-java-uuid/src/test/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/core-java-modules/core-java-uuid/src/test/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+    
+        
+            %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/README.md b/core-java-modules/core-java/README.md
index f1cf2d8c09..a75805e0c2 100644
--- a/core-java-modules/core-java/README.md
+++ b/core-java-modules/core-java/README.md
@@ -3,13 +3,7 @@
 ### Relevant Articles: 
 - [Getting Started with Java Properties](http://www.baeldung.com/java-properties)
 - [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency)
-- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
-- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
 - [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
 - [Introduction to Javadoc](http://www.baeldung.com/javadoc)
-- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)
-- [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid)
 - [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle)
 - [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties)
-- [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities)
-- [Generating Alphanumeric UUID String in Java](https://www.baeldung.com/java-generate-alphanumeric-uuid)
diff --git a/core-java-modules/core-java/pom.xml b/core-java-modules/core-java/pom.xml
index db2b1edc70..188c6a6f63 100644
--- a/core-java-modules/core-java/pom.xml
+++ b/core-java-modules/core-java/pom.xml
@@ -49,18 +49,16 @@
             ${lombok.version}
             provided
         
-        
-        
-            org.assertj
-            assertj-core
-            ${assertj-core.version}
-            test
-        
         
             org.javamoney
             moneta
             ${javamoney.moneta.version}
         
+        
+            org.springframework
+            spring-core
+            ${spring.core.version}
+        
     
 
     
@@ -180,13 +178,12 @@
         
         0.4
         1.8.7
-        
-        3.10.0
         
         1.1
         3.0.0-M1
         1.8
         1.8
+        4.3.20.RELEASE
     
 
 
\ No newline at end of file
diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/javadoc/CodeSnippetFormatting.java b/core-java-modules/core-java/src/main/java/com/baeldung/javadoc/CodeSnippetFormatting.java
new file mode 100644
index 0000000000..2bb9614e66
--- /dev/null
+++ b/core-java-modules/core-java/src/main/java/com/baeldung/javadoc/CodeSnippetFormatting.java
@@ -0,0 +1,154 @@
+package com.baeldung.javadoc;
+
+public class CodeSnippetFormatting {
+
+    /**
+     * This is an example to show default behavior of code snippet formatting in Javadocs
+     * 
+     * public class Application(){
+     * 
+     * }
+     * 
+     */
+    public void showCodeSnippetFormatting() {
+        // do nothing
+    }
+
+    /**
+     * This is an example to show usage of HTML pre tag while code snippet formatting in Javadocs
+     * 
+     * 
+     * public class Application(){
+     *     List nums = new ArrayList<>();
+     * }
+     * 
+     * 
+ */ + public void showCodeSnippetFormattingUsingPRETag() { + // do nothing + } + + /** + * This is an example to show usage of HTML character entities while code snippet formatting in Javadocs + * + *
+     * public class Application(){
+     *     List<Integer> nums = new ArrayList<>();
+     * }
+     * 
+     * 
+ */ + public void showCodeSnippetFormattingUsingCharacterEntities() { + // do nothing + } + + /** + * This is an example to show usage of javadoc code tag while code snippet formatting in Javadocs + * + *
+     * 
+     * public class Application(){
+     *     {@code List nums = new ArrayList<>(); }
+     * }
+     *
+     * 
+ */ + public void showCodeSnippetFormattingUsingCodeTag() { + // do nothing + } + + /** + * This is an example to show issue faced while using annotations in Javadocs + * + *
+     * 
+     * public class Application(){
+     *            @Getter
+     *     {@code List nums = new ArrayList<>(); }
+     * }
+     *
+     * 
+ */ + public void showCodeSnippetFormattingIssueUsingCodeTag() { + // do nothing + } + + /** + * This is an example to show usage of javadoc code tag for handling '@' character + * + *
+     * 
+     * public class Application(){
+     *     {@code @Getter}
+     *     {@code List nums = new ArrayList<>(); }
+     * }
+     *
+     * 
+ */ + public void showCodeSnippetAnnotationFormattingUsingCodeTag() { + // do nothing + } + + + /** + * This is an example to show difference in javadoc literal and code tag + * + *

+ * + * {@literal @Getter} + * {@literal List nums = new ArrayList<>(); } + * + *
+ * {@code @Getter} + * {@code List nums = new ArrayList<>(); } + *

+ */ + public void showCodeSnippetCommentsFormattingUsingCodeAndLiteralTag() { + // do nothing + } + + /** + * This is an example to illustrate a basic jQuery code snippet embedded in documentation comments + *
+     * {@code }
+     * 
+ */ + public void showJSCodeSnippetUsingJavadoc() { + // do nothing + } + + /** + * This is an example to illustrate an HTML code snippet embedded in documentation comments + *
{@code
+     * 
+     * 
+     * 

Hello World!

+ * + * } + *
+ * + */ + public void showHTMLCodeSnippetUsingJavadoc() { + // do nothing + } + + /** + * This is an example to illustrate an HTML code snippet embedded in documentation comments + *
+     * 
+     * 
+     * 

Hello World!

+ * + * + *
+ * + */ + public void showHTMLCodeSnippetIssueUsingJavadoc() { + // do nothing + } + +} diff --git a/core-java-modules/multimodulemavenproject/README.md b/core-java-modules/multimodulemavenproject/README.md index fc4ca60b6b..13d87c36ec 100644 --- a/core-java-modules/multimodulemavenproject/README.md +++ b/core-java-modules/multimodulemavenproject/README.md @@ -1,3 +1,4 @@ ## Relevant Articles - [Multi-Module Maven Application with Java Modules](https://www.baeldung.com/maven-multi-module-project-java-jpms) +- [Importing Maven Project into Eclipse](https://www.baeldung.com/maven-import-eclipse) diff --git a/core-java-modules/multimodulemavenproject/pom.xml b/core-java-modules/multimodulemavenproject/pom.xml index 79d884cd86..fbafa7ebff 100644 --- a/core-java-modules/multimodulemavenproject/pom.xml +++ b/core-java-modules/multimodulemavenproject/pom.xml @@ -23,17 +23,6 @@ mainappmodule - - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - - @@ -54,7 +43,6 @@ 3.8.0 1.9 1.9 - 3.12.2
\ No newline at end of file diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 9f184310e9..a25cf11454 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -46,6 +46,7 @@ core-java-concurrency-advanced-4 core-java-concurrency-basic core-java-concurrency-basic-2 + core-java-concurrency-basic-3 core-java-concurrency-collections core-java-concurrency-collections-2 core-java-console @@ -55,6 +56,7 @@ core-java-exceptions core-java-exceptions-2 core-java-exceptions-3 + core-java-exceptions-4 core-java-function core-java-functional core-java-io @@ -90,7 +92,6 @@ core-java-lang-syntax-2 core-java-networking core-java-networking-2 - core-java-networking-3 core-java-nio core-java-nio-2 core-java-optional @@ -99,13 +100,15 @@ core-java-reflection-2 core-java-security core-java-security-2 + core-java-security-3 + core-java-serialization + core-java-security-algorithms core-java-streams core-java-streams-2 core-java-streams-3 core-java-streams-4 core-java-string-algorithms core-java-string-algorithms-2 - core-java-string-algorithms-3 core-java-string-apis core-java-string-conversions core-java-string-conversions-2 @@ -114,6 +117,7 @@ core-java-sun core-java-regex core-java-regex-2 + core-java-uuid pre-jpms @@ -134,8 +138,4 @@ - - 2.22.2 - - diff --git a/core-java-modules/pre-jpms/pom.xml b/core-java-modules/pre-jpms/pom.xml index 60e425b936..cd4bd0faa3 100644 --- a/core-java-modules/pre-jpms/pom.xml +++ b/core-java-modules/pre-jpms/pom.xml @@ -12,7 +12,6 @@ com.baeldung.core-java-modules core-java-modules 0.0.1-SNAPSHOT - ../ diff --git a/ddd-modules/pom.xml b/ddd-modules/pom.xml index fe3aaf1160..134a9d0566 100644 --- a/ddd-modules/pom.xml +++ b/ddd-modules/pom.xml @@ -39,12 +39,6 @@ ${junit-jupiter.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - @@ -80,8 +74,6 @@ 3.8.1 1.0 - - 3.12.2 diff --git a/ddd/pom.xml b/ddd/pom.xml index cc5a173e85..3beb43bb35 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -86,11 +86,6 @@ spring-boot-starter-test test - - org.mockito - mockito-core - test - de.flapdoodle.embed de.flapdoodle.embed.mongo diff --git a/discord4j/pom.xml b/discord4j/pom.xml index 1e73e5109b..e15bd47583 100644 --- a/discord4j/pom.xml +++ b/discord4j/pom.xml @@ -43,7 +43,7 @@ com.discord4j discord4j-core - 3.1.1 + ${discord4j-core.version} @@ -66,6 +66,7 @@ 1.8 + 3.1.1 \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 8aca8e4293..0de3694215 100644 --- a/docker/README.md +++ b/docker/README.md @@ -5,3 +5,4 @@ - [Running Spring Boot with PostgreSQL in Docker Compose](https://www.baeldung.com/spring-boot-postgresql-docker) - [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/ops/docker-jvm-heap-size) - [Dockerfile Strategies for Git](https://www.baeldung.com/ops/dockerfile-git-strategies) +- [How to Get Docker-Compose to Always Use the Latest Image](https://www.baeldung.com/ops/docker-compose-latest-image) diff --git a/docker/docker-include-outside-build-context/projects/config/Dockerfile b/docker/docker-include-outside-build-context/projects/config/Dockerfile new file mode 100644 index 0000000000..754f9f9be3 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/config/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx:latest +COPY nginx.conf /etc/nginx/nginx.conf diff --git a/docker/docker-include-outside-build-context/projects/config/nginx.conf b/docker/docker-include-outside-build-context/projects/config/nginx.conf new file mode 100644 index 0000000000..944da2f112 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/config/nginx.conf @@ -0,0 +1,8 @@ +events {} + +http { + server { + listen 80; + index index.html; + } +} diff --git a/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile new file mode 100644 index 0000000000..bda0bbe257 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:latest +COPY sample-site/html/* /etc/nginx/html/ +COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-from-base b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-from-base new file mode 100644 index 0000000000..1b72414bc0 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-from-base @@ -0,0 +1,2 @@ +FROM sample-site-base:latest +COPY html/* /etc/nginx/html/ diff --git a/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-script b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-script new file mode 100644 index 0000000000..572028f19f --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/sample-site/docker/Dockerfile-script @@ -0,0 +1,3 @@ +FROM nginx:latest +COPY html/* /etc/nginx/html/ +COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker/docker-include-outside-build-context/projects/sample-site/docker/build-docker.sh b/docker/docker-include-outside-build-context/projects/sample-site/docker/build-docker.sh new file mode 100755 index 0000000000..e84687b7b7 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/sample-site/docker/build-docker.sh @@ -0,0 +1,6 @@ +mkdir tmp-context +cp -R ../html tmp-context/ +cp -R ../../config tmp-context/ +cp Dockerfile-script tmp-context/Dockerfile +docker build -t sample-site:latest tmp-context +rm -rf tmp-context diff --git a/docker/docker-include-outside-build-context/projects/sample-site/html/index.html b/docker/docker-include-outside-build-context/projects/sample-site/html/index.html new file mode 100644 index 0000000000..85f287fad7 --- /dev/null +++ b/docker/docker-include-outside-build-context/projects/sample-site/html/index.html @@ -0,0 +1,10 @@ + + + + + Sample Site + + +

Welcome to the first page of the site

+ + diff --git a/docker/docker-sample-app/Dockerfile b/docker/docker-sample-app/Dockerfile new file mode 100644 index 0000000000..71fc1a29d9 --- /dev/null +++ b/docker/docker-sample-app/Dockerfile @@ -0,0 +1,3 @@ +FROM openjdk:11 +COPY target/docker-sample-app-0.0.1.jar app.jar +ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/docker/docker-sample-app/README.md b/docker/docker-sample-app/README.md new file mode 100644 index 0000000000..6aeaa1d2a3 --- /dev/null +++ b/docker/docker-sample-app/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- How to Get Docker-Compose to Always Use the Latest Image diff --git a/docker/docker-sample-app/docker-compose-build-image.yaml b/docker/docker-sample-app/docker-compose-build-image.yaml new file mode 100644 index 0000000000..27c1d8ee44 --- /dev/null +++ b/docker/docker-sample-app/docker-compose-build-image.yaml @@ -0,0 +1,8 @@ +version: '2.4' +services: + db: + image: postgres + my_app: + build: . + ports: + - "8080:8080" diff --git a/docker/docker-sample-app/docker-compose-with-image.yaml b/docker/docker-sample-app/docker-compose-with-image.yaml new file mode 100644 index 0000000000..9a8822f762 --- /dev/null +++ b/docker/docker-sample-app/docker-compose-with-image.yaml @@ -0,0 +1,9 @@ +version: '2.4' +services: + db: + image: postgres + my_app: + image: "eugen/test-app:latest" + ports: + - "8080:8080" + diff --git a/guest/remote-debugging/pom.xml b/docker/docker-sample-app/pom.xml similarity index 54% rename from guest/remote-debugging/pom.xml rename to docker/docker-sample-app/pom.xml index 4541160e37..6841fabcee 100644 --- a/guest/remote-debugging/pom.xml +++ b/docker/docker-sample-app/pom.xml @@ -1,33 +1,39 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.stackify - remote-debugging - 0.0.1-SNAPSHOT - remote-debugging - war - - org.springframework.boot - spring-boot-starter-parent - 1.5.8.RELEASE - + com.baeldung.docker + docker + 0.0.1 + docker-sample-app + docker-sample-app + Demo project for Spring Boot and Docker + + + 11 + + org.springframework.boot - spring-boot-starter-web + spring-boot-starter org.springframework.boot - spring-boot-starter-tomcat + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test - remote-debugging org.springframework.boot @@ -36,9 +42,4 @@ - - UTF-8 - UTF-8 - - diff --git a/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/DockAppApplication.java b/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/DockAppApplication.java new file mode 100644 index 0000000000..e7ff52015c --- /dev/null +++ b/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/DockAppApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.docker.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DockAppApplication { + + public static void main(String[] args) { + SpringApplication.run(DockAppApplication.class, args); + } + +} diff --git a/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/endpoint/MyController.java b/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/endpoint/MyController.java new file mode 100644 index 0000000000..d46c57e606 --- /dev/null +++ b/docker/docker-sample-app/src/main/java/com/baeldung/docker/app/endpoint/MyController.java @@ -0,0 +1,13 @@ +package com.baeldung.docker.app.endpoint; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MyController { + + @GetMapping + public String version() { + return "1.7"; + } +} diff --git a/docker/docker-sample-app/src/main/resources/application.properties b/docker/docker-sample-app/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/docker/docker-sample-app/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/docker/docker-sample-app/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java b/docker/docker-sample-app/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java new file mode 100644 index 0000000000..7220766988 --- /dev/null +++ b/docker/docker-sample-app/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java @@ -0,0 +1,13 @@ +package com.baeldung.docker.app; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DockAppApplicationUnitTest { + + @Test + void contextLoads() { + } + +} diff --git a/docker/pom.xml b/docker/pom.xml index 3fcc9ca94f..f481f1b8b7 100644 --- a/docker/pom.xml +++ b/docker/pom.xml @@ -25,6 +25,7 @@ docker-internal-dto docker-spring-boot + docker-sample-app diff --git a/drools/pom.xml b/drools/pom.xml index cc96d9d032..daaf1fa8a7 100644 --- a/drools/pom.xml +++ b/drools/pom.xml @@ -19,7 +19,6 @@ httpcore ${http-component-version}
- org.kie kie-ci diff --git a/eclipse/formatter.xml b/eclipse/formatter.xml deleted file mode 100644 index 6887946a4c..0000000000 --- a/eclipse/formatter.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ethereum/pom.xml b/ethereum/pom.xml index 7fc4057341..6c1a0e900f 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -144,24 +144,6 @@ test - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.hamcrest - hamcrest-core - - - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - com.jayway.jsonpath json-path @@ -209,7 +191,6 @@ 1.5.0-RELEASE 3.3.1 1.5.6.RELEASE - 2.21.0 2.4.0 2.0.4.RELEASE 3.1 diff --git a/feign/README.md b/feign/README.md index 03051671d5..eeff55a4d4 100644 --- a/feign/README.md +++ b/feign/README.md @@ -5,4 +5,5 @@ This module contains articles about Feign ### Relevant Articles: - [Intro to Feign](https://www.baeldung.com/intro-to-feign) +- [Retrying Feign Calls](https://www.baeldung.com/feign-retry) diff --git a/feign/pom.xml b/feign/pom.xml index 56059d2a77..cf28890868 100644 --- a/feign/pom.xml +++ b/feign/pom.xml @@ -11,7 +11,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - .. diff --git a/feign/src/main/java/com/baeldung/feign/retry/Custom5xxErrorDecoder.java b/feign/src/main/java/com/baeldung/feign/retry/Custom5xxErrorDecoder.java new file mode 100644 index 0000000000..6ff3c42ba1 --- /dev/null +++ b/feign/src/main/java/com/baeldung/feign/retry/Custom5xxErrorDecoder.java @@ -0,0 +1,27 @@ +package com.baeldung.feign.retry; + + +import feign.FeignException; +import feign.Response; +import feign.RetryableException; +import feign.codec.ErrorDecoder; + +import static feign.FeignException.errorStatus; + +public class Custom5xxErrorDecoder implements ErrorDecoder { + @Override + public Exception decode(String methodKey, Response response) { + FeignException exception = errorStatus(methodKey, response); + int status = response.status(); + if (status >= 500) { + return new RetryableException( + response.status(), + exception.getMessage(), + response.request().httpMethod(), + exception, + null, + response.request()); + } + return exception; + } +} diff --git a/feign/src/main/java/com/baeldung/feign/retry/NaiveRetryer.java b/feign/src/main/java/com/baeldung/feign/retry/NaiveRetryer.java new file mode 100644 index 0000000000..5a3c13fadd --- /dev/null +++ b/feign/src/main/java/com/baeldung/feign/retry/NaiveRetryer.java @@ -0,0 +1,21 @@ +package com.baeldung.feign.retry; + +import feign.RetryableException; +import feign.Retryer; + +public class NaiveRetryer implements feign.Retryer { + @Override + public void continueOrPropagate(RetryableException e) { + try { + Thread.sleep(1000L); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw e; + } + } + + @Override + public Retryer clone() { + return new NaiveRetryer(); + } +} diff --git a/feign/src/main/java/com/baeldung/feign/retry/ResilientFeignClientBuilder.java b/feign/src/main/java/com/baeldung/feign/retry/ResilientFeignClientBuilder.java new file mode 100644 index 0000000000..d8285d362a --- /dev/null +++ b/feign/src/main/java/com/baeldung/feign/retry/ResilientFeignClientBuilder.java @@ -0,0 +1,28 @@ +package com.baeldung.feign.retry; + +import com.baeldung.feign.clients.BookClient; +import feign.Feign; +import feign.Logger; +import feign.Retryer; +import feign.gson.GsonDecoder; +import feign.gson.GsonEncoder; +import feign.okhttp.OkHttpClient; +import feign.slf4j.Slf4jLogger; +import lombok.Getter; + +import java.util.concurrent.TimeUnit; + +@Getter +public class ResilientFeignClientBuilder { + public BookClient bookClient = createClient(BookClient.class, "http://localhost:8081/api/books"); + + public static T createClient(Class type, String uri) { + return Feign.builder() + .client(new OkHttpClient()) + .encoder(new GsonEncoder()) + .decoder(new GsonDecoder()) + .retryer(new Retryer.Default(100L, TimeUnit.SECONDS.toMillis(3L), 5)) + .errorDecoder(new Custom5xxErrorDecoder()) + .target(type, uri); + } +} diff --git a/feign/src/test/java/com/baeldung/feign/retry/Custom5xxErrorDecoderUnitTest.java b/feign/src/test/java/com/baeldung/feign/retry/Custom5xxErrorDecoderUnitTest.java new file mode 100644 index 0000000000..8c43b42b76 --- /dev/null +++ b/feign/src/test/java/com/baeldung/feign/retry/Custom5xxErrorDecoderUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.feign.retry; + +import feign.*; +import feign.codec.ErrorDecoder; +import org.jetbrains.annotations.NotNull; +import org.junit.Test; + +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.HashMap; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Custom5xxErrorDecoderUnitTest { + @Test + public void given5xxResponse_whenDecode_thenReturnRetryableException() { + // given + ErrorDecoder decoder = new Custom5xxErrorDecoder(); + Response response = responseStub(500); + + // when + Exception exception = decoder.decode("GET", response); + + // then + assertTrue(exception instanceof RetryableException); + } + + @Test + public void given4xxResponse_whenDecode_thenReturnFeignException() { + // given + ErrorDecoder decoder = new Custom5xxErrorDecoder(); + Response response = responseStub(400); + + // when + Exception exception = decoder.decode("GET", response); + + // then + assertTrue(exception instanceof FeignException); + assertFalse(exception instanceof RetryableException); + } + + @NotNull + private Response responseStub(int status) { + return Response.builder() + .request(Request.create( + Request.HttpMethod.GET, "url", new HashMap<>(), new byte[0], Charset.defaultCharset(), new RequestTemplate())) + .status(status) + .build(); + } +} diff --git a/flyway-cdi-extension/pom.xml b/flyway-cdi-extension/pom.xml index dbd21374e2..3d52ff0e36 100644 --- a/flyway-cdi-extension/pom.xml +++ b/flyway-cdi-extension/pom.xml @@ -11,7 +11,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - .. diff --git a/google-web-toolkit/pom.xml b/google-web-toolkit/pom.xml index 1a49ced021..bcccc136a4 100644 --- a/google-web-toolkit/pom.xml +++ b/google-web-toolkit/pom.xml @@ -44,12 +44,6 @@ gwt-dev provided - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - diff --git a/gradle/gradle-source-vs-target-compatibility/build.gradle b/gradle/gradle-source-vs-target-compatibility/build.gradle new file mode 100644 index 0000000000..8cc50c15c6 --- /dev/null +++ b/gradle/gradle-source-vs-target-compatibility/build.gradle @@ -0,0 +1,12 @@ +plugins { + id 'java' +} + +description = 'gradle-source-vs-target-compatibility' + +group 'com.baeldung' + +java { + sourceCompatibility = "1.6" + targetCompatibility = "1.8" +} diff --git a/gradle/gradle-source-vs-target-compatibility/src/main/java/com/baeldung/helloworld/HelloWorldApp.java b/gradle/gradle-source-vs-target-compatibility/src/main/java/com/baeldung/helloworld/HelloWorldApp.java new file mode 100644 index 0000000000..a951a72dd6 --- /dev/null +++ b/gradle/gradle-source-vs-target-compatibility/src/main/java/com/baeldung/helloworld/HelloWorldApp.java @@ -0,0 +1,9 @@ +package com.baeldung.helloworld; + +public class HelloWorldApp { + + public static void main(String[] args) { + System.out.println("Hello World!"); + } + +} diff --git a/gradle/maven-to-gradle/README.md b/gradle/maven-to-gradle/README.md new file mode 100644 index 0000000000..bd6e435c9a --- /dev/null +++ b/gradle/maven-to-gradle/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +[Convert a Maven Build to Gradle](https://www.baeldung.com/maven-convert-to-gradle) diff --git a/gradle/maven-to-gradle/build.gradle b/gradle/maven-to-gradle/build.gradle new file mode 100644 index 0000000000..71a9360f91 --- /dev/null +++ b/gradle/maven-to-gradle/build.gradle @@ -0,0 +1,31 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java' + id 'maven-publish' +} + +repositories { + mavenLocal() + maven { + url = 'http://repo.maven.apache.org/maven2' + } +} + +dependencies { + implementation 'org.apache.commons:commons-lang3:3.12.0' +} + +group = 'com.balendung' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '1.8' + +publishing { + publications { + maven(MavenPublication) { + from(components.java) + } + } +} diff --git a/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.jar b/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..f3d88b1c2f Binary files /dev/null and b/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.properties b/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..ba94df8451 --- /dev/null +++ b/gradle/maven-to-gradle/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradle/maven-to-gradle/gradlew b/gradle/maven-to-gradle/gradlew new file mode 100644 index 0000000000..2fe81a7d95 --- /dev/null +++ b/gradle/maven-to-gradle/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradle/maven-to-gradle/gradlew.bat b/gradle/maven-to-gradle/gradlew.bat new file mode 100644 index 0000000000..9618d8d960 --- /dev/null +++ b/gradle/maven-to-gradle/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gradle/maven-to-gradle/pom.xml b/gradle/maven-to-gradle/pom.xml new file mode 100644 index 0000000000..32eaf63d9c --- /dev/null +++ b/gradle/maven-to-gradle/pom.xml @@ -0,0 +1,15 @@ + + 4.0.0 + com.baeldung + maven-to-gradle + 0.0.1-SNAPSHOT + + + org.apache.commons + commons-lang3 + 3.12.0 + + + diff --git a/gradle/maven-to-gradle/settings.gradle b/gradle/maven-to-gradle/settings.gradle new file mode 100644 index 0000000000..8a7251a5c2 --- /dev/null +++ b/gradle/maven-to-gradle/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'maven-to-gradle' diff --git a/gradle/maven-to-gradle/src/main/java/com/sample/javacode/DisplayTime.java b/gradle/maven-to-gradle/src/main/java/com/sample/javacode/DisplayTime.java new file mode 100644 index 0000000000..1e96d46ee9 --- /dev/null +++ b/gradle/maven-to-gradle/src/main/java/com/sample/javacode/DisplayTime.java @@ -0,0 +1,21 @@ +package com.sample.javacode; + +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; + +public class DisplayTime { + + public static void main(String[] args) { + Date date = new java.util.Date(); + System.out.println(date); + String gmt = date.toString(); + boolean flag = StringUtils.isEmpty(gmt); + if (flag) { + System.out.println("No time found"); + } else { + System.out.println(gmt); + } + } + +} diff --git a/gradle/settings.gradle b/gradle/settings.gradle index 59300f9281..d1eb10f4d2 100644 --- a/gradle/settings.gradle +++ b/gradle/settings.gradle @@ -6,5 +6,6 @@ include 'greeter' include 'gradletaskdemo' include 'junit5' include 'gradle-employee-app' +include 'gradle-source-vs-target-compatibility' println 'This will be executed during the initialization phase.' diff --git a/graphql/graphql-dgs/README.md b/graphql/graphql-dgs/README.md new file mode 100644 index 0000000000..6614891b31 --- /dev/null +++ b/graphql/graphql-dgs/README.md @@ -0,0 +1,7 @@ +## GraphQL Domain Graph Service (DGS) + +This module contains articles about GraphQL using the Netflix Domain Graph Service (DGS). + +## Relevant articles: + +- [An Introduction to Domain Graph Service (DGS) Framework](https://www.baeldung.com/spring-boot-domain-graph-service) diff --git a/graphql/graphql-dgs/pom.xml b/graphql/graphql-dgs/pom.xml new file mode 100644 index 0000000000..1dc3630276 --- /dev/null +++ b/graphql/graphql-dgs/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + com.baeldung.graphql-dgs + graphql-dgs + 1.0 + graphql-dgs + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../.. + + + + + + com.netflix.graphql.dgs + graphql-dgs-platform-dependencies + 4.1.0 + pom + import + + + + + + + org.springframework.boot + spring-boot-starter + 2.6.2 + + + + org.springframework.boot + spring-boot-starter-test + 2.6.2 + test + + + + com.netflix.graphql.dgs.codegen + graphql-dgs-codegen-client-core + 5.1.14 + + + + org.springframework.boot + spring-boot-starter-web + 2.6.2 + + + + com.netflix.graphql.dgs + graphql-dgs-spring-boot-starter + 4.9.15 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.6.2 + + + io.github.deweyjose + graphqlcodegen-maven-plugin + 1.14 + + + + generate + + + + + + src/main/resources/schema/schema.graphqls + + com.bealdung.graphqldgs.generated + + + + + + diff --git a/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Album.java b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Album.java new file mode 100644 index 0000000000..7e53eb08fe --- /dev/null +++ b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Album.java @@ -0,0 +1,25 @@ +package com.bealdung.graphqlDGS; + +public class Album { + private final String title; + private final String artist; + private final Integer recordNo; + + public Album(String title, String artist, Integer recordNo) { + this.title = title; + this.recordNo = recordNo; + this.artist = artist; + } + + public String getTitle() { + return title; + } + + public String getArtist() { + return artist; + } + + public Integer getRecordNo() { + return recordNo; + } +} diff --git a/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/AlbumsDataFetcher.java b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/AlbumsDataFetcher.java new file mode 100644 index 0000000000..8fda98b941 --- /dev/null +++ b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/AlbumsDataFetcher.java @@ -0,0 +1,28 @@ +package com.bealdung.graphqlDGS; + +import com.netflix.graphql.dgs.DgsComponent; +import com.netflix.graphql.dgs.DgsQuery; +import com.netflix.graphql.dgs.InputArgument; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@DgsComponent +public class AlbumsDataFetcher { + + private final List albums = Arrays.asList( + new Album("Rumours", "Fleetwood Mac", 20), + new Album("What's Going On", "Marvin Gaye", 10), + new Album("Pet Sounds", "The Beach Boys", 12) + ); + + @DgsQuery + public List albums(@InputArgument String titleFilter) { + if(titleFilter == null) { + return albums; + } + return albums.stream() + .filter(s -> s.getTitle().contains(titleFilter)) + .collect(Collectors.toList()); + } +} diff --git a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/Application.java b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Application.java similarity index 62% rename from guest/spring-security/src/main/java/com/stackify/guest/springsecurity/Application.java rename to graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Application.java index fbd0eee044..ffe8cb2a4e 100644 --- a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/Application.java +++ b/graphql/graphql-dgs/src/main/java/com/bealdung/graphqlDGS/Application.java @@ -1,11 +1,9 @@ -package com.stackify.guest.springsecurity; +package com.bealdung.graphqlDGS; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; @SpringBootApplication -@ComponentScan(basePackages = {"com.stackify.guest.springsecurity"}) public class Application { public static void main(String[] args) { diff --git a/graphql/graphql-dgs/src/main/resources/application.properties b/graphql/graphql-dgs/src/main/resources/application.properties new file mode 100644 index 0000000000..8693adcbd6 --- /dev/null +++ b/graphql/graphql-dgs/src/main/resources/application.properties @@ -0,0 +1 @@ +server.servlet.context-path= diff --git a/graphql/graphql-dgs/src/main/resources/schema/schema.graphqls b/graphql/graphql-dgs/src/main/resources/schema/schema.graphqls new file mode 100644 index 0000000000..90691a7204 --- /dev/null +++ b/graphql/graphql-dgs/src/main/resources/schema/schema.graphqls @@ -0,0 +1,9 @@ +type Query { + albums(titleFilter: String): [Album] +} + +type Album { + title: String + artist: String + recordNo: Int +} diff --git a/graphql/graphql-java/pom.xml b/graphql/graphql-java/pom.xml index eae30aa8fa..4e2444c1fb 100644 --- a/graphql/graphql-java/pom.xml +++ b/graphql/graphql-java/pom.xml @@ -12,7 +12,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../.. diff --git a/grpc/pom.xml b/grpc/pom.xml index f034b2b517..40284c90fe 100644 --- a/grpc/pom.xml +++ b/grpc/pom.xml @@ -1,88 +1,84 @@ - 4.0.0 - grpc - 0.0.1-SNAPSHOT - grpc - jar + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + grpc + 0.0.1-SNAPSHOT + grpc + jar - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - io.grpc - grpc-netty-shaded - runtime - ${io.grpc.version} - - - io.grpc - grpc-protobuf - ${io.grpc.version} - - - io.grpc - grpc-stub - ${io.grpc.version} - - - io.grpc - grpc-testing - ${io.grpc.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - javax.annotation - javax.annotation-api - 1.2 - - + + + io.grpc + grpc-netty-shaded + runtime + ${io.grpc.version} + + + io.grpc + grpc-protobuf + ${io.grpc.version} + + + io.grpc + grpc-stub + ${io.grpc.version} + + + io.grpc + grpc-testing + ${io.grpc.version} + test + + + javax.annotation + javax.annotation-api + 1.2 + + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + + com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:${io.grpc.version}:exe:${os.detected.classifier} + + + + + compile + compile-custom + + + + + + + + + 1.40.1 + 3.17.2 + 1.6.2 + 0.6.1 + - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - ${protobuf-maven-plugin.version} - - com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:${io.grpc.version}:exe:${os.detected.classifier} - - - - - compile - compile-custom - - - - - - - - 1.40.1 - 3.17.2 - 1.6.2 - 0.6.1 - \ No newline at end of file diff --git a/gson/pom.xml b/gson/pom.xml index a928d87b61..082e53baf0 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -61,10 +61,7 @@ - 2.8.0 - - 4.1 2.9.6 diff --git a/guava-modules/guava-18/pom.xml b/guava-modules/guava-18/pom.xml index ed295db2f4..8f5108bff1 100644 --- a/guava-modules/guava-18/pom.xml +++ b/guava-modules/guava-18/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ diff --git a/guava-modules/guava-19/pom.xml b/guava-modules/guava-19/pom.xml index 3c29a2a59c..ba85fe0ae8 100644 --- a/guava-modules/guava-19/pom.xml +++ b/guava-modules/guava-19/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ diff --git a/guava-modules/guava-21/pom.xml b/guava-modules/guava-21/pom.xml index 8b7c3cdcfd..9e791bfe23 100644 --- a/guava-modules/guava-21/pom.xml +++ b/guava-modules/guava-21/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ diff --git a/guava-modules/guava-collections-list/pom.xml b/guava-modules/guava-collections-list/pom.xml index e57198ec40..6863b4011c 100644 --- a/guava-modules/guava-collections-list/pom.xml +++ b/guava-modules/guava-collections-list/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ @@ -27,25 +26,6 @@ ${commons-lang3.version} - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - org.hamcrest java-hamcrest @@ -65,10 +45,6 @@ - - 4.1 - - 3.6.1 2.0.0.0 diff --git a/guava-modules/guava-collections-map/pom.xml b/guava-modules/guava-collections-map/pom.xml index 7f3e470fc3..04beaa13a1 100644 --- a/guava-modules/guava-collections-map/pom.xml +++ b/guava-modules/guava-collections-map/pom.xml @@ -12,24 +12,8 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - guava-collections-map diff --git a/guava-modules/guava-collections-set/pom.xml b/guava-modules/guava-collections-set/pom.xml index 09e3f42e83..49bfc46ee2 100644 --- a/guava-modules/guava-collections-set/pom.xml +++ b/guava-modules/guava-collections-set/pom.xml @@ -11,38 +11,10 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ - - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - guava-collections-set - - - 3.6.1 - - \ No newline at end of file diff --git a/guava-modules/guava-collections/pom.xml b/guava-modules/guava-collections/pom.xml index 6dc7510a1e..9283107023 100644 --- a/guava-modules/guava-collections/pom.xml +++ b/guava-modules/guava-collections/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ @@ -32,25 +31,6 @@ ${jool.version} - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - org.hamcrest java-hamcrest @@ -70,11 +50,7 @@ - - 4.1 0.9.12 - - 3.6.1 2.0.0.0 diff --git a/guava-modules/guava-core/pom.xml b/guava-modules/guava-core/pom.xml index a15dfb5178..dd68fef43a 100644 --- a/guava-modules/guava-core/pom.xml +++ b/guava-modules/guava-core/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ @@ -20,13 +19,6 @@ commons-lang3 ${commons-lang3.version} - - - org.assertj - assertj-core - ${assertj.version} - test - @@ -39,9 +31,4 @@ - - - 3.6.1 - - \ No newline at end of file diff --git a/guava-modules/guava-io/pom.xml b/guava-modules/guava-io/pom.xml index 11a5d4ada6..2ea91c5e4f 100644 --- a/guava-modules/guava-io/pom.xml +++ b/guava-modules/guava-io/pom.xml @@ -11,24 +11,8 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - guava-io diff --git a/guava-modules/guava-utilities/pom.xml b/guava-modules/guava-utilities/pom.xml index 6049a62e85..ab849072a5 100644 --- a/guava-modules/guava-utilities/pom.xml +++ b/guava-modules/guava-utilities/pom.xml @@ -11,7 +11,6 @@ com.baeldung guava-modules 0.0.1-SNAPSHOT - ../ @@ -20,25 +19,6 @@ commons-lang3 ${commons-lang3.version} - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - @@ -51,9 +31,4 @@ - - - 3.6.1 - - \ No newline at end of file diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml index cbfb47fa0f..d5b01d3402 100644 --- a/guava-modules/pom.xml +++ b/guava-modules/pom.xml @@ -34,23 +34,6 @@ guava ${guava.version} - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - 2.22.2 - 29.0-jre - - \ No newline at end of file diff --git a/guest/core-java-9/pom.xml b/guest/core-java-9/pom.xml deleted file mode 100644 index 786f85ce86..0000000000 --- a/guest/core-java-9/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - com.stackify - core-java-9 - 0.0.1-SNAPSHOT - core-java-9 - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - - - - - - - 1.9 - 1.9 - - - \ No newline at end of file diff --git a/guest/core-java-9/src/main/java/com/stackify/optional/User.java b/guest/core-java-9/src/main/java/com/stackify/optional/User.java deleted file mode 100644 index 903e75f6f6..0000000000 --- a/guest/core-java-9/src/main/java/com/stackify/optional/User.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stackify.optional; - -public class User { - private String email; - private String password; - - public User(String email, String password) { - super(); - this.email = email; - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/guest/core-java-9/src/test/java/com/stackify/optional/OptionalTest.java b/guest/core-java-9/src/test/java/com/stackify/optional/OptionalTest.java deleted file mode 100644 index 4c3503b811..0000000000 --- a/guest/core-java-9/src/test/java/com/stackify/optional/OptionalTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.stackify.optional; - -import org.junit.Test; -import java.util.Optional; -import java.util.List; - -import static org.junit.Assert.*; -import java.util.stream.Collectors; - -public class OptionalTest { - - private User user; - - @Test - public void whenEmptyOptional_thenGetValueFromOr() { - User result = Optional.ofNullable(user) - .or( () -> Optional.of(new User("default","1234"))).get(); - - assertEquals(result.getEmail(), "default"); - } - - @Test - public void whenIfPresentOrElse_thenOk() { - Optional.ofNullable(user) - .ifPresentOrElse( u -> System.out.println("User is:" + u.getEmail()), () -> System.out.println("User not found")); - } - - @Test - public void whenGetStream_thenOk() { - User user = new User("john@gmail.com", "1234"); - List emails = Optional.ofNullable(user) - .stream() - .filter(u -> u.getEmail() != null && u.getEmail().contains("@")) - .map( u -> u.getEmail()) - .collect(Collectors.toList()); - - assertTrue(emails.size() == 1); - assertEquals(emails.get(0), user.getEmail()); - } - -} diff --git a/guest/core-java/pom.xml b/guest/core-java/pom.xml deleted file mode 100644 index aaf67fd27e..0000000000 --- a/guest/core-java/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - com.stackify - core-java - 0.0.1-SNAPSHOT - core-java - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - org.apache.logging.log4j - log4j-core - ${log4j2.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - 2.8.2 - 3.6.1 - - - \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optional/Address.java b/guest/core-java/src/main/java/com/stackify/optional/Address.java deleted file mode 100644 index f54c999920..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/Address.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.stackify.optional; - -public class Address { - private String addressLine; - private String city; - private Country country; - - public Address(String addressLine, String city, Country country) { - super(); - this.addressLine = addressLine; - this.city = city; - this.country = country; - } - - public String getAddressLine() { - return addressLine; - } - - public void setAddressLine(String addressLine) { - this.addressLine = addressLine; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public Country getCountry() { - return country; - } - - public void setCountry(Country country) { - this.country = country; - } - - -} diff --git a/guest/core-java/src/main/java/com/stackify/optional/Country.java b/guest/core-java/src/main/java/com/stackify/optional/Country.java deleted file mode 100644 index bf97ef7b6d..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/Country.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.stackify.optional; - -public class Country { - private String name; - private String isocode; - - public Country(String name, String isocode) { - super(); - this.name = name; - this.isocode = isocode; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getIsocode() { - return isocode; - } - - public void setIsocode(String isocode) { - this.isocode = isocode; - } - -} diff --git a/guest/core-java/src/main/java/com/stackify/optional/User.java b/guest/core-java/src/main/java/com/stackify/optional/User.java deleted file mode 100644 index 910f2605dd..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/User.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.stackify.optional; - -import java.util.Optional; - -public class User { - private String email; - private String password; - - private Address address; - - private String position; - - public User(String email, String password) { - super(); - this.email = email; - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Address getAddress() { - return address; - } - - public void setAddress(Address address) { - this.address = address; - } - - public Optional getPosition() { - return Optional.ofNullable(position); - } - - public void setPosition(String position) { - this.position = position; - } - -} diff --git a/guest/core-java/src/main/java/com/stackify/optional/chaining/Address.java b/guest/core-java/src/main/java/com/stackify/optional/chaining/Address.java deleted file mode 100644 index 1e10c67c39..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/chaining/Address.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.optional.chaining; - -import java.util.Optional; - -public class Address { - private String addressLine; - private String city; - private Country country; - - public Address(String addressLine, String city) { - this.addressLine = addressLine; - this.city = city; - } - - public String getAddressLine() { - return addressLine; - } - - public void setAddressLine(String addressLine) { - this.addressLine = addressLine; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public Optional getCountry() { - return Optional.ofNullable(country); - } - - public void setCountry(Country country) { - this.country = country; - } -} diff --git a/guest/core-java/src/main/java/com/stackify/optional/chaining/Country.java b/guest/core-java/src/main/java/com/stackify/optional/chaining/Country.java deleted file mode 100644 index 89e85a9b43..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/chaining/Country.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stackify.optional.chaining; - -public class Country { - private String name; - private String isocode; - - public Country(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getIsocode() { - return isocode; - } - - public void setIsocode(String isocode) { - this.isocode = isocode; - } - - -} \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optional/chaining/User.java b/guest/core-java/src/main/java/com/stackify/optional/chaining/User.java deleted file mode 100644 index 07eb398abe..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optional/chaining/User.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.stackify.optional.chaining; - -import java.util.Optional; - -public class User { - private String email; - private String password; - - private Address address; - - private String position; - - public User(String email, String password) { - this.email = email; - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Optional
getAddress() { - return Optional.ofNullable(address); - } - - public void setAddress(Address address) { - this.address = address; - } - - public Optional getPosition() { - return Optional.ofNullable(position); - } - - public void setPosition(String position) { - this.position = position; - } - -} diff --git a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitamin.java b/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitamin.java deleted file mode 100644 index 90cb49b321..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitamin.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.stackify.optionalparams; - -public class MultiVitamin { - - private String name; // required - private int vitaminA; // in mcg - private int vitaminC; // in mg - private int calcium; // in mg - private int iron; // in mg - - public MultiVitamin(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public int getVitaminA() { - return vitaminA; - } - - public void setVitaminA(int vitaminA) { - this.vitaminA = vitaminA; - } - - public int getVitaminC() { - return vitaminC; - } - - public void setVitaminC(int vitaminC) { - this.vitaminC = vitaminC; - } - - public int getCalcium() { - return calcium; - } - - public void setCalcium(int calcium) { - this.calcium = calcium; - } - - public int getIron() { - return iron; - } - - public void setIron(int iron) { - this.iron = iron; - } -} \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminAllowingNulls.java b/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminAllowingNulls.java deleted file mode 100644 index 1d2a61354d..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminAllowingNulls.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.optionalparams; - -public class MultiVitaminAllowingNulls { - - private String name; // required - private Integer vitaminA; // in mcg - private Integer vitaminC; // in mg - private Integer calcium; // in mg - private Integer iron; // in mg - - public MultiVitaminAllowingNulls(String name, Integer vitaminA, Integer vitaminC, Integer calcium, Integer iron) { - this.name = name; - this.vitaminA = vitaminA; - this.vitaminC = vitaminC; - this.calcium = calcium; - this.iron = iron; - } - - public String getName() { - return name; - } - - public Integer getVitaminA() { - return vitaminA; - } - - public Integer getVitaminC() { - return vitaminC; - } - - public Integer getCalcium() { - return calcium; - } - - public Integer getIron() { - return iron; - } -} \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminOverloading.java b/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminOverloading.java deleted file mode 100644 index e9dcb2509b..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminOverloading.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.stackify.optionalparams; - -public class MultiVitaminOverloading { - - static final int DEFAULT_IRON_AMOUNT = 20; - - private final String name; // required - private final int vitaminA; // in mcg - private final int vitaminC; // in mg - private final int calcium; // in mg - private final int iron; // in mg - - public MultiVitaminOverloading(String name) { - this(name, 0); - } - - public MultiVitaminOverloading(String name, int vitaminA) { - this(name, vitaminA, 0); - } - - public MultiVitaminOverloading(String name, int vitaminA, int vitaminC) { - this(name, vitaminA, vitaminC, 0); - } - - public MultiVitaminOverloading(String name, int vitaminA, int vitaminC, int calcium) { - this(name, vitaminA, vitaminC, calcium, DEFAULT_IRON_AMOUNT); - } - - public MultiVitaminOverloading(String name, int vitaminA, int vitaminC, int calcium, int iron) { - this.name = name; - this.vitaminA = vitaminA; - this.vitaminC = vitaminC; - this.calcium = calcium; - this.iron = iron; - } - - public String getName() { - return name; - } - - public int getVitaminA() { - return vitaminA; - } - - public int getVitaminC() { - return vitaminC; - } - - public int getCalcium() { - return calcium; - } - - public int getIron() { - return iron; - } -} \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminStaticFactoryMethods.java b/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminStaticFactoryMethods.java deleted file mode 100644 index 229a2f0004..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminStaticFactoryMethods.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.stackify.optionalparams; - -public class MultiVitaminStaticFactoryMethods { - - static final int IRON_AMT_DEF = 20; - static final int IRON_AMT_MEN = 30; - - static final int CALCIUM_AMT_DEF = 100; - static final int CALCIUM_AMT_WOMEN = 120; - - private final String name; // required - private final int vitaminA; // in mcg - private final int vitaminC; // in mg - private final int calcium; // in mg - private final int iron; // in mg - - public static MultiVitaminStaticFactoryMethods forMen(String name) { - return new MultiVitaminStaticFactoryMethods(name, 5000, 60, CALCIUM_AMT_DEF, IRON_AMT_MEN); - } - - public static MultiVitaminStaticFactoryMethods forWomen(String name) { - return new MultiVitaminStaticFactoryMethods(name, 5000, 60, CALCIUM_AMT_WOMEN, IRON_AMT_DEF); - } - - private MultiVitaminStaticFactoryMethods(String name, int vitaminA, int vitaminC, int calcium, int iron) { - this.name = name; - this.vitaminA = vitaminA; - this.vitaminC = vitaminC; - this.calcium = calcium; - this.iron = iron; - } - - public String getName() { - return name; - } - - public int getVitaminA() { - return vitaminA; - } - - public int getVitaminC() { - return vitaminC; - } - - public int getCalcium() { - return calcium; - } - - public int getIron() { - return iron; - } -} \ No newline at end of file diff --git a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminWithBuilder.java b/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminWithBuilder.java deleted file mode 100644 index 8097074b86..0000000000 --- a/guest/core-java/src/main/java/com/stackify/optionalparams/MultiVitaminWithBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.stackify.optionalparams; - -public class MultiVitaminWithBuilder { - - private final String name; // required - private final int vitaminA; // in mcg - private final int vitaminC; // in mg - private final int calcium; // in mg - private final int iron; // in mg - - private MultiVitaminWithBuilder(MultiVitaminBuilder builder) { - this.name = builder.name; - this.vitaminA = builder.vitaminA; - this.vitaminC = builder.vitaminC; - this.calcium = builder.calcium; - this.iron = builder.iron; - } - - public String getName() { - return name; - } - - public int getVitaminA() { - return vitaminA; - } - - public int getVitaminC() { - return vitaminC; - } - - public int getCalcium() { - return calcium; - } - - public int getIron() { - return iron; - } - - public static class MultiVitaminBuilder { - - private static final int ZERO = 0; - - private final String name; // required - private int vitaminA = ZERO; - private int vitaminC = ZERO; - private int calcium = ZERO; - private int iron = ZERO; - - public MultiVitaminBuilder(String name) { - this.name = name; - } - - public MultiVitaminBuilder withVitaminA(int vitaminA) { - this.vitaminA = vitaminA; - return this; - } - - public MultiVitaminBuilder withVitaminC(int vitaminC) { - this.vitaminC = vitaminC; - return this; - } - - public MultiVitaminBuilder withCalcium(int calcium) { - this.calcium = calcium; - return this; - } - - public MultiVitaminBuilder withIron(int iron) { - this.iron = iron; - return this; - } - - public MultiVitaminWithBuilder build() { - return new MultiVitaminWithBuilder(this); - } - } -} diff --git a/guest/core-java/src/main/java/com/stackify/stream/Employee.java b/guest/core-java/src/main/java/com/stackify/stream/Employee.java deleted file mode 100644 index 005990c863..0000000000 --- a/guest/core-java/src/main/java/com/stackify/stream/Employee.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.stackify.stream; - -public class Employee { - private Integer id; - private String name; - private Double salary; - - public Employee(Integer id, String name, Double salary) { - this.id = id; - this.name = name; - this.salary = salary; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Double getSalary() { - return salary; - } - - public void setSalary(Double salary) { - this.salary = salary; - } - - public void salaryIncrement(Double percentage) { - Double newSalary = salary + percentage * salary / 100; - setSalary(newSalary); - } - - public String toString() { - return "Id: " + id + " Name:" + name + " Price:" + salary; - } -} diff --git a/guest/core-java/src/main/java/com/stackify/stream/EmployeeRepository.java b/guest/core-java/src/main/java/com/stackify/stream/EmployeeRepository.java deleted file mode 100644 index 223fee5e26..0000000000 --- a/guest/core-java/src/main/java/com/stackify/stream/EmployeeRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.stackify.stream; - -import java.util.List; - -public class EmployeeRepository { - private List empList; - - public EmployeeRepository(List empList) { - this.empList = empList; - - } - public Employee findById(Integer id) { - for (Employee emp : empList) { - if (emp.getId() == id) { - return emp; - } - } - - return null; - } -} diff --git a/guest/core-java/src/main/resources/log4j2.xml b/guest/core-java/src/main/resources/log4j2.xml deleted file mode 100644 index a67aae6aa6..0000000000 --- a/guest/core-java/src/main/resources/log4j2.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/core-java/src/test/java/com/stackify/optional/OptionalTest.java b/guest/core-java/src/test/java/com/stackify/optional/OptionalTest.java deleted file mode 100644 index c6e6ddb15d..0000000000 --- a/guest/core-java/src/test/java/com/stackify/optional/OptionalTest.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.stackify.optional; - -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.Test; - -public class OptionalTest { - - private User user; - - private Logger logger = LogManager.getLogger(OptionalTest.class); - - @Test(expected = NullPointerException.class) - public void testNull() { - String isocode = user.getAddress().getCountry().getIsocode().toUpperCase(); - } - - @Test - public void test() { - - if (user != null) { - Address address = user.getAddress(); - if (address != null) { - Country country = address.getCountry(); - if (country != null) { - String isocode = country.getIsocode(); - if (isocode != null) { - isocode = isocode.toUpperCase(); - } - } - } - } - - } - - @Test(expected = NoSuchElementException.class) - public void whenCreateEmptyOptional_thenNull() { - Optional emptyOpt = Optional.empty(); - emptyOpt.get(); - } - - @Test(expected = NullPointerException.class) - public void whenCreateOfEmptyOptional_thenNullPointerException() { - Optional opt = Optional.of(user); - } - - @Test - public void whenCreateOfNullableOptional_thenOk() { - String name = "John"; - Optional opt = Optional.ofNullable(name); - assertEquals("John", opt.get()); - } - - @Test - public void whenCheckIsPresent_thenOk() { - user = new User("john@gmail.com", "1234"); - Optional opt = Optional.ofNullable(user); - assertTrue(opt.isPresent()); - - assertEquals(user.getEmail(), opt.get().getEmail()); - } - - @Test - public void whenCheckIfPresent_thenOk() { - user = new User("john@gmail.com", "1234"); - Optional opt = Optional.ofNullable(user); - assertTrue(opt.isPresent()); - - opt.ifPresent(u -> assertEquals(user.getEmail(), u.getEmail())); - } - - @Test - public void whenEmptyValue_thenReturnDefault() { - User user = null; - User user2 = new User("anna@gmail.com", "1234"); - User result = Optional.ofNullable(user).orElse(user2); - - assertEquals("anna@gmail.com", result.getEmail()); - } - - @Test - public void whenValueNotNull_thenIgnoreDefault() { - User user = new User("john@gmail.com", "1234"); - User user2 = new User("anna@gmail.com", "1234"); - User result = Optional.ofNullable(user).orElse(user2); - - assertEquals("john@gmail.com", result.getEmail()); - } - - @Test - public void whenSetDefaultOrElseGet_thenOk() { - User user = null; - User user2 = new User("anna@gmail.com", "1234"); - User result = Optional.ofNullable(user).orElseGet(() -> user2); - - assertEquals("anna@gmail.com", result.getEmail()); - } - - @Test - public void givenPresentValue_whenCompare_thenOk() { - User user = new User("john@gmail.com", "1234"); - logger.info("Using orElse"); - User result = Optional.ofNullable(user).orElse(createNewUser()); - logger.info("Using orElseGet"); - User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser()); - } - - private User createNewUser() { - logger.info("Creating New User"); - return new User("extra@gmail.com", "1234"); - } - - @Test - public void givenEmptyValue_whenCompare_thenOk() { - User user = null; - logger.info("Using orElse"); - User result = Optional.ofNullable(user).orElse(createNewUser()); - logger.info("Using orElseGet"); - User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenThrowException_thenOk() { - User result = Optional.ofNullable(user).orElseThrow(() -> new IllegalArgumentException()); - } - - @Test - public void whenMap_thenOk() { - user = new User("anna@gmail.com", "1234"); - String email = Optional.ofNullable(user).map(u -> u.getEmail()).orElse("default@gmail.com"); - assertEquals(email, user.getEmail()); - - } - - @Test - public void whenFlatMap_thenOk() { - user = new User("anna@gmail.com", "1234"); - user.setPosition("Developer"); - String position = Optional.ofNullable(user).flatMap(u -> u.getPosition()).orElse("default"); - assertEquals(position, user.getPosition().get()); - - } - - @Test - public void whenFilter_thenOk() { - user = new User("anna@gmail.com", "1234"); - Optional result = Optional.ofNullable(user).filter(u -> u.getEmail() != null && u.getEmail().contains("@")); - - assertTrue(result.isPresent()); - } - - @Test - public void whenStream_thenOk() { - List users = new ArrayList<>(); - User user = users.stream().findFirst().orElse(new User("default", "1234")); - assertEquals(user.getEmail(), "default"); - } - -} diff --git a/guest/core-java/src/test/java/com/stackify/optional/chaining/OptionalChainingTest.java b/guest/core-java/src/test/java/com/stackify/optional/chaining/OptionalChainingTest.java deleted file mode 100644 index 660497c367..0000000000 --- a/guest/core-java/src/test/java/com/stackify/optional/chaining/OptionalChainingTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.stackify.optional.chaining; - -import static org.junit.Assert.*; - -import java.util.Optional; - -import org.junit.Test; - -public class OptionalChainingTest { - - @Test - public void whenChaining_thenOk() { - User user = new User("anna@gmail.com", "1234"); - - String result = Optional.ofNullable(user) - .flatMap(u -> u.getAddress()) - .flatMap(a -> a.getCountry()) - .map(c -> c.getIsocode()) - .orElse("default"); - - assertEquals(result, "default"); - } - - @Test - public void whenChainingWithMethodReferences_thenOk() { - User user = new User("anna@gmail.com", "1234"); - - String result = Optional.ofNullable(user) - .flatMap(User::getAddress) - .flatMap(Address::getCountry) - .map(Country::getIsocode) - .orElse("default"); - - assertEquals(result, "default"); - } -} diff --git a/guest/core-java/src/test/java/com/stackify/optionalparams/OptionalParamsUnitTest.java b/guest/core-java/src/test/java/com/stackify/optionalparams/OptionalParamsUnitTest.java deleted file mode 100644 index 947ce83a90..0000000000 --- a/guest/core-java/src/test/java/com/stackify/optionalparams/OptionalParamsUnitTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.stackify.optionalparams; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.math.BigDecimal; - -import org.assertj.core.util.Arrays; -import org.junit.Test; - -public class OptionalParamsUnitTest { - - @Test - public void whenCreateMultiVitaminWithOverloading_thenOk() { - MultiVitaminOverloading multiVitamin = new MultiVitaminOverloading("Default Multivitamin"); - - assertThat(multiVitamin.getName()).isEqualTo("Default Multivitamin"); - assertThat(multiVitamin.getVitaminA()).isEqualTo(0); - assertThat(multiVitamin.getVitaminC()).isEqualTo(0); - assertThat(multiVitamin.getCalcium()).isEqualTo(0); - assertThat(multiVitamin.getIron()).isEqualTo(MultiVitaminOverloading.DEFAULT_IRON_AMOUNT); - } - - @Test - public void whenCreateMultiVitaminWithStaticFactoryMethods_thenOk() { - MultiVitaminStaticFactoryMethods mensMultiVitamin = MultiVitaminStaticFactoryMethods.forMen("Complete for Men"); - - assertThat(mensMultiVitamin.getName()).isEqualTo("Complete for Men"); - assertThat(mensMultiVitamin.getCalcium()).isEqualTo(MultiVitaminStaticFactoryMethods.CALCIUM_AMT_DEF); - assertThat(mensMultiVitamin.getIron()).isEqualTo(MultiVitaminStaticFactoryMethods.IRON_AMT_MEN); - - MultiVitaminStaticFactoryMethods womensMultiVitamin = MultiVitaminStaticFactoryMethods.forWomen("Complete for Women"); - - assertThat(womensMultiVitamin.getName()).isEqualTo("Complete for Women"); - assertThat(womensMultiVitamin.getCalcium()).isEqualTo(MultiVitaminStaticFactoryMethods.CALCIUM_AMT_WOMEN); - assertThat(womensMultiVitamin.getIron()).isEqualTo(MultiVitaminStaticFactoryMethods.IRON_AMT_DEF); - } - - @Test - public void whenCreateMultiVitaminWithBuilder_thenOk() { - MultiVitaminWithBuilder vitamin = new MultiVitaminWithBuilder.MultiVitaminBuilder("Maximum Strength") - .withCalcium(100) - .withIron(200) - .withVitaminA(50) - .withVitaminC(1000) - .build(); - - assertThat(vitamin.getName()).isEqualTo("Maximum Strength"); - assertThat(vitamin.getCalcium()).isEqualTo(100); - assertThat(vitamin.getIron()).isEqualTo(200); - assertThat(vitamin.getVitaminA()).isEqualTo(50); - assertThat(vitamin.getVitaminC()).isEqualTo(1000); - } - - @Test - public void whenCreateMutliVitaminWithAccessors_thenOk() { - MultiVitamin vitamin = new MultiVitamin("Generic"); - vitamin.setVitaminA(50); - vitamin.setVitaminC(1000); - vitamin.setCalcium(100); - vitamin.setIron(200); - - assertThat(vitamin.getName()).isEqualTo("Generic"); - assertThat(vitamin.getCalcium()).isEqualTo(100); - assertThat(vitamin.getIron()).isEqualTo(200); - assertThat(vitamin.getVitaminA()).isEqualTo(50); - assertThat(vitamin.getVitaminC()).isEqualTo(1000); - } - - @Test - public void whenCreateMultiVitaminWithNulls_thenOk() { - MultiVitamin vitamin = new MultiVitamin(null); - - assertThat(vitamin.getName()).isNull(); - } - - public void varArgsDemo() { - Object[] args = Arrays.array(Long.valueOf(1), Integer.valueOf(2), BigDecimal.valueOf(3)); - - processVarArgsWithCastingAntiPattern(args); - } - - private void processVarArgsWithCastingAntiPattern(Object... args) { - String message = "processing %s as %s"; - - // never do this sort of thing - for (Object arg : args) { - if (arg instanceof Long) { - System.out.println(String.format(message, arg, "Long")); - } else if (arg instanceof Integer) { - System.out.println(String.format(message, arg, "Integer")); - } else if (arg instanceof BigDecimal) { - System.out.println(String.format(message, arg, "BigDecimal")); - } - } - } -} diff --git a/guest/core-java/src/test/java/com/stackify/stream/EmployeeTest.java b/guest/core-java/src/test/java/com/stackify/stream/EmployeeTest.java deleted file mode 100644 index cf988d035a..0000000000 --- a/guest/core-java/src/test/java/com/stackify/stream/EmployeeTest.java +++ /dev/null @@ -1,455 +0,0 @@ -package com.stackify.stream; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.DoubleSummaryStatistics; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Set; -import java.util.Vector; -import java.util.function.BinaryOperator; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.After; -import org.junit.Test; - -public class EmployeeTest { - private String fileName = "src/test/resources/test.txt"; - - private static Employee[] arrayOfEmps = { - new Employee(1, "Jeff Bezos", 100000.0), - new Employee(2, "Bill Gates", 200000.0), - new Employee(3, "Mark Zuckerberg", 300000.0) - }; - - private static List empList = Arrays.asList(arrayOfEmps); - private static EmployeeRepository employeeRepository = new EmployeeRepository(empList); - - @After - public void cleanup() throws IOException { - Files.deleteIfExists(Paths.get(fileName)); - } - - @Test - public void whenGetStreamFromList_ObtainStream() { - assert(empList.stream() instanceof Stream); - } - - @Test - public void whenGetStreamFromArray_ObtainStream() { - assert(Stream.of(arrayOfEmps) instanceof Stream); - } - - @Test - public void whenGetStreamFromElements_ObtainStream() { - assert(Stream.of(arrayOfEmps[0], arrayOfEmps[1], arrayOfEmps[2]) instanceof Stream); - } - - @Test - public void whenBuildStreamFromElements_ObtainStream() { - Stream.Builder empStreamBuilder = Stream.builder(); - - empStreamBuilder.accept(arrayOfEmps[0]); - empStreamBuilder.accept(arrayOfEmps[1]); - empStreamBuilder.accept(arrayOfEmps[2]); - - Stream empStream = empStreamBuilder.build(); - - assert(empStream instanceof Stream); - } - - @Test - public void whenIncrementSalaryForEachEmployee_thenApplyNewSalary() { - Employee[] arrayOfEmps = { - new Employee(1, "Jeff Bezos", 100000.0), - new Employee(2, "Bill Gates", 200000.0), - new Employee(3, "Mark Zuckerberg", 300000.0) - }; - - List empList = Arrays.asList(arrayOfEmps); - - empList.stream().forEach(e -> e.salaryIncrement(10.0)); - - assertThat(empList, contains( - hasProperty("salary", equalTo(110000.0)), - hasProperty("salary", equalTo(220000.0)), - hasProperty("salary", equalTo(330000.0)) - )); - } - - @Test - public void whenIncrementSalaryUsingPeek_thenApplyNewSalary() { - Employee[] arrayOfEmps = { - new Employee(1, "Jeff Bezos", 100000.0), - new Employee(2, "Bill Gates", 200000.0), - new Employee(3, "Mark Zuckerberg", 300000.0) - }; - - List empList = Arrays.asList(arrayOfEmps); - - empList.stream() - .peek(e -> e.salaryIncrement(10.0)) - .peek(System.out::println) - .collect(Collectors.toList()); - - assertThat(empList, contains( - hasProperty("salary", equalTo(110000.0)), - hasProperty("salary", equalTo(220000.0)), - hasProperty("salary", equalTo(330000.0)) - )); - } - - @Test - public void whenMapIdToEmployees_thenGetEmployeeStream() { - Integer[] empIds = { 1, 2, 3 }; - - List employees = Stream.of(empIds) - .map(employeeRepository::findById) - .collect(Collectors.toList()); - - assertEquals(employees.size(), empIds.length); - } - - @Test - public void whenFlatMapEmployeeNames_thenGetNameStream() { - List> namesNested = Arrays.asList( - Arrays.asList("Jeff", "Bezos"), - Arrays.asList("Bill", "Gates"), - Arrays.asList("Mark", "Zuckerberg")); - - List namesFlatStream = namesNested.stream() - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - assertEquals(namesFlatStream.size(), namesNested.size() * 2); - } - - @Test - public void whenFilterEmployees_thenGetFilteredStream() { - Integer[] empIds = { 1, 2, 3, 4 }; - - List employees = Stream.of(empIds) - .map(employeeRepository::findById) - .filter(e -> e != null) - .filter(e -> e.getSalary() > 200000) - .collect(Collectors.toList()); - - assertEquals(Arrays.asList(arrayOfEmps[2]), employees); - } - - @Test - public void whenFindFirst_thenGetFirstEmployeeInStream() { - Integer[] empIds = { 1, 2, 3, 4 }; - - Employee employee = Stream.of(empIds) - .map(employeeRepository::findById) - .filter(e -> e != null) - .filter(e -> e.getSalary() > 100000) - .findFirst() - .orElse(null); - - assertEquals(employee.getSalary(), new Double(200000)); - } - - @Test - public void whenCollectStreamToList_thenGetList() { - List employees = empList.stream().collect(Collectors.toList()); - - assertEquals(empList, employees); - } - - @Test - public void whenStreamToArray_thenGetArray() { - Employee[] employees = empList.stream().toArray(Employee[]::new); - - assertThat(empList.toArray(), equalTo(employees)); - } - - @Test - public void whenStreamCount_thenGetElementCount() { - Long empCount = empList.stream() - .filter(e -> e.getSalary() > 200000) - .count(); - - assertEquals(empCount, new Long(1)); - } - - @Test - public void whenLimitInfiniteStream_thenGetFiniteElements() { - Stream infiniteStream = Stream.iterate(2, i -> i * 2); - - List collect = infiniteStream - .skip(3) - .limit(5) - .collect(Collectors.toList()); - - assertEquals(collect, Arrays.asList(16, 32, 64, 128, 256)); - } - - @Test - public void whenSortStream_thenGetSortedStream() { - List employees = empList.stream() - .sorted((e1, e2) -> e1.getName().compareTo(e2.getName())) - .collect(Collectors.toList()); - - assertEquals(employees.get(0).getName(), "Bill Gates"); - assertEquals(employees.get(1).getName(), "Jeff Bezos"); - assertEquals(employees.get(2).getName(), "Mark Zuckerberg"); - } - - - @Test - public void whenFindMin_thenGetMinElementFromStream() { - Employee firstEmp = empList.stream() - .min((e1, e2) -> e1.getId() - e2.getId()) - .orElseThrow(NoSuchElementException::new); - - assertEquals(firstEmp.getId(), new Integer(1)); - } - - @Test - public void whenFindMax_thenGetMaxElementFromStream() { - Employee maxSalEmp = empList.stream() - .max(Comparator.comparing(Employee::getSalary)) - .orElseThrow(NoSuchElementException::new); - - assertEquals(maxSalEmp.getSalary(), new Double(300000.0)); - } - - @Test - public void whenApplyDistinct_thenRemoveDuplicatesFromStream() { - List intList = Arrays.asList(2, 5, 3, 2, 4, 3); - List distinctIntList = intList.stream().distinct().collect(Collectors.toList()); - - assertEquals(distinctIntList, Arrays.asList(2, 5, 3, 4)); - } - - @Test - public void whenApplyMatch_thenReturnBoolean() { - List intList = Arrays.asList(2, 4, 5, 6, 8); - - boolean allEven = intList.stream().allMatch(i -> i % 2 == 0); - boolean oneEven = intList.stream().anyMatch(i -> i % 2 == 0); - boolean noneMultipleOfThree = intList.stream().noneMatch(i -> i % 3 == 0); - - assertEquals(allEven, false); - assertEquals(oneEven, true); - assertEquals(noneMultipleOfThree, false); - } - - @Test - public void whenFindMaxOnIntStream_thenGetMaxInteger() { - Integer latestEmpId = empList.stream() - .mapToInt(Employee::getId) - .max() - .orElseThrow(NoSuchElementException::new); - - assertEquals(latestEmpId, new Integer(3)); - } - - @Test - public void whenApplySumOnIntStream_thenGetSum() { - Double avgSal = empList.stream() - .mapToDouble(Employee::getSalary) - .average() - .orElseThrow(NoSuchElementException::new); - - assertEquals(avgSal, new Double(200000)); - } - - @Test - public void whenApplyReduceOnStream_thenGetValue() { - Double sumSal = empList.stream() - .map(Employee::getSalary) - .reduce(0.0, Double::sum); - - assertEquals(sumSal, new Double(600000)); - } - - @Test - public void whenCollectByJoining_thenGetJoinedString() { - String empNames = empList.stream() - .map(Employee::getName) - .collect(Collectors.joining(", ")) - .toString(); - - assertEquals(empNames, "Jeff Bezos, Bill Gates, Mark Zuckerberg"); - } - - @Test - public void whenCollectBySet_thenGetSet() { - Set empNames = empList.stream() - .map(Employee::getName) - .collect(Collectors.toSet()); - - assertEquals(empNames.size(), 3); - } - - @Test - public void whenToVectorCollection_thenGetVector() { - Vector empNames = empList.stream() - .map(Employee::getName) - .collect(Collectors.toCollection(Vector::new)); - - assertEquals(empNames.size(), 3); - } - - @Test - public void whenApplySummarizing_thenGetBasicStats() { - DoubleSummaryStatistics stats = empList.stream() - .collect(Collectors.summarizingDouble(Employee::getSalary)); - - assertEquals(stats.getCount(), 3); - assertEquals(stats.getSum(), 600000.0, 0); - assertEquals(stats.getMin(), 100000.0, 0); - assertEquals(stats.getMax(), 300000.0, 0); - assertEquals(stats.getAverage(), 200000.0, 0); - } - - @Test - public void whenApplySummaryStatistics_thenGetBasicStats() { - DoubleSummaryStatistics stats = empList.stream() - .mapToDouble(Employee::getSalary) - .summaryStatistics(); - - assertEquals(stats.getCount(), 3); - assertEquals(stats.getSum(), 600000.0, 0); - assertEquals(stats.getMin(), 100000.0, 0); - assertEquals(stats.getMax(), 300000.0, 0); - assertEquals(stats.getAverage(), 200000.0, 0); - } - - @Test - public void whenStreamPartition_thenGetMap() { - List intList = Arrays.asList(2, 4, 5, 6, 8); - Map> isEven = intList.stream().collect( - Collectors.partitioningBy(i -> i % 2 == 0)); - - assertEquals(isEven.get(true).size(), 4); - assertEquals(isEven.get(false).size(), 1); - } - - @Test - public void whenStreamGroupingBy_thenGetMap() { - Map> groupByAlphabet = empList.stream().collect( - Collectors.groupingBy(e -> new Character(e.getName().charAt(0)))); - - assertEquals(groupByAlphabet.get('B').get(0).getName(), "Bill Gates"); - assertEquals(groupByAlphabet.get('J').get(0).getName(), "Jeff Bezos"); - assertEquals(groupByAlphabet.get('M').get(0).getName(), "Mark Zuckerberg"); - } - - @Test - public void whenStreamMapping_thenGetMap() { - Map> idGroupedByAlphabet = empList.stream().collect( - Collectors.groupingBy(e -> new Character(e.getName().charAt(0)), - Collectors.mapping(Employee::getId, Collectors.toList()))); - - assertEquals(idGroupedByAlphabet.get('B').get(0), new Integer(2)); - assertEquals(idGroupedByAlphabet.get('J').get(0), new Integer(1)); - assertEquals(idGroupedByAlphabet.get('M').get(0), new Integer(3)); - } - - @Test - public void whenStreamReducing_thenGetValue() { - Double percentage = 10.0; - Double salIncrOverhead = empList.stream().collect(Collectors.reducing( - 0.0, e -> e.getSalary() * percentage / 100, (s1, s2) -> s1 + s2)); - - assertEquals(salIncrOverhead, 60000.0, 0); - } - - @Test - public void whenStreamGroupingAndReducing_thenGetMap() { - Comparator byNameLength = Comparator.comparing(Employee::getName); - - Map> longestNameByAlphabet = empList.stream().collect( - Collectors.groupingBy(e -> new Character(e.getName().charAt(0)), - Collectors.reducing(BinaryOperator.maxBy(byNameLength)))); - - assertEquals(longestNameByAlphabet.get('B').get().getName(), "Bill Gates"); - assertEquals(longestNameByAlphabet.get('J').get().getName(), "Jeff Bezos"); - assertEquals(longestNameByAlphabet.get('M').get().getName(), "Mark Zuckerberg"); - } - - @Test - public void whenParallelStream_thenPerformOperationsInParallel() { - Employee[] arrayOfEmps = { - new Employee(1, "Jeff Bezos", 100000.0), - new Employee(2, "Bill Gates", 200000.0), - new Employee(3, "Mark Zuckerberg", 300000.0) - }; - - List empList = Arrays.asList(arrayOfEmps); - - empList.stream().parallel().forEach(e -> e.salaryIncrement(10.0)); - - assertThat(empList, contains( - hasProperty("salary", equalTo(110000.0)), - hasProperty("salary", equalTo(220000.0)), - hasProperty("salary", equalTo(330000.0)) - )); - } - - @Test - public void whenGenerateStream_thenGetInfiniteStream() { - Stream.generate(Math::random) - .limit(5) - .forEach(System.out::println); - } - - @Test - public void whenIterateStream_thenGetInfiniteStream() { - Stream evenNumStream = Stream.iterate(2, i -> i * 2); - - List collect = evenNumStream - .limit(5) - .collect(Collectors.toList()); - - assertEquals(collect, Arrays.asList(2, 4, 8, 16, 32)); - } - - @Test - public void whenStreamToFile_thenGetFile() throws IOException { - String[] words = { - "hello", - "refer", - "world", - "level" - }; - - try (PrintWriter pw = new PrintWriter( - Files.newBufferedWriter(Paths.get(fileName)))) { - Stream.of(words).forEach(pw::println); - } - } - - private List getPalindrome(Stream stream, int length) { - return stream.filter(s -> s.length() == length) - .filter(s -> s.compareToIgnoreCase( - new StringBuilder(s).reverse().toString()) == 0) - .collect(Collectors.toList()); - } - - @Test - public void whenFileToStream_thenGetStream() throws IOException { - whenStreamToFile_thenGetFile(); - - List str = getPalindrome(Files.lines(Paths.get(fileName)), 5); - assertThat(str, contains("refer", "level")); - } -} diff --git a/guest/core-kotlin/.gitignore b/guest/core-kotlin/.gitignore deleted file mode 100644 index 0c017e8f8c..0000000000 --- a/guest/core-kotlin/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/bin/ - -#ignore gradle -.gradle/ - - -#ignore build and generated files -build/ -node/ -out/ - -#ignore installed node modules and package lock file -node_modules/ -package-lock.json diff --git a/guest/core-kotlin/README.md b/guest/core-kotlin/README.md deleted file mode 100644 index fad62ebea6..0000000000 --- a/guest/core-kotlin/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Kotlin vs Java](https://www.baeldung.com/kotlin/vs-java) diff --git a/guest/core-kotlin/pom.xml b/guest/core-kotlin/pom.xml deleted file mode 100644 index 91bc7fa170..0000000000 --- a/guest/core-kotlin/pom.xml +++ /dev/null @@ -1,201 +0,0 @@ - - - 4.0.0 - com.stackify - core-kotlin - 1.0-SNAPSHOT - core-kotlin - jar - - - - jcenter - http://jcenter.bintray.com - - - - - - org.junit.platform - junit-platform-runner - ${junit-platform.version} - test - - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin-stdlib.version} - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin-stdlib.version} - - - org.jetbrains.kotlin - kotlin-test-junit - ${kotlin-test-junit.version} - test - - - org.jetbrains.kotlin - kotlin-reflect - ${kotlin-reflect.version} - - - org.jetbrains.spek - spek-api - ${spek.api.version} - test - - - org.jetbrains.spek - spek-subject-extension - ${spek.subject.version} - test - - - org.jetbrains.spek - spek-junit-platform-engine - ${spek.junit.version} - test - - - com.nhaarman - mockito-kotlin - ${mockito-kotlin.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - - org.apache.maven.plugins - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - test - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin-maven-plugin.version} - provided - - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin-maven-plugin.version} - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - - - - - test-compile - - test-compile - - - - ${project.basedir}/src/test/kotlin - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java.version} - ${java.version} - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - - - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit-platform-surefire-provider.version} - - - - - junit5 - - integration-test - verify - - - - **/*Test5.java - - - - - - - - - - 2.22.0 - UTF-8 - 1.2.60 - 1.2.51 - 1.2.51 - 1.2.51 - 0.22.5 - 1.5.0 - 3.6.1 - 3.10.0 - 3.7.0 - 1.1.5 - 1.1.5 - 1.1.5 - - - diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/CompanionObjectTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/CompanionObjectTest.kt deleted file mode 100644 index 69573fb75b..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/CompanionObjectTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals - -class CompanionObjectTest { - - @Test - fun givenAClassWithCompanionObject_whenCallingMethodTheSameAsStaticOne_thenWeGetAResult() { - assertEquals("A", A.returnClassName()) - } - -} - -class A { - companion object { - fun returnClassName(): String { - return "A" - } - } -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ConstructorTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ConstructorTest.kt deleted file mode 100644 index fdb5d05db5..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ConstructorTest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals - -class ConstructorTests { - - @Test - fun givenAClassWithPrimaryConstructor_whenCreatingAnInstance_thenWeGetObject() { - var example = Example(1, "Example") - - assertEquals(1, example.id) - assertEquals("Example", example.name) - } - -} - -class Example constructor(val id: Int, var name: String) \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DataClassTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DataClassTest.kt deleted file mode 100644 index ad79538d3c..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DataClassTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse - -class DataClassTest { - - @Test - fun givenASampleDataClass_whenCallingToStringMethod_thenItReturnsAllProperties() { - val student = Student(1, "John", "Smith") - - assertEquals(1, student.id) - assertEquals("John", student.name) - assertEquals("Smith", student.lastName) - assertEquals("Student(id=1, name=John, lastName=Smith)", student.toString()) - } - - @Test - fun givenASampleDataClass_whenCreatingACopyWithGeneratedFunction_thenItReturnsACopyWithRequestedChanges() { - val student = Student(1, "John", "Smith") - val student2 = student.copy(id = 2, name = "Anne") - - assertEquals(2, student2.id) - assertEquals("Anne", student2.name) - assertEquals("Smith", student2.lastName) - assertEquals("Student(id=2, name=Anne, lastName=Smith)", student2.toString()) - assertFalse(student.equals(student2)) - } - -} - -data class Student(val id: Int, val name: String, val lastName: String) \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DelegationTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DelegationTest.kt deleted file mode 100644 index 2da824c2db..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/DelegationTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals - -class DelegationTest { - - @Test - fun givenAClassWithDelegation_whenCallDelegatedMethod_thenWeGetAResultDefinedInPassedObject() { - val car = Car(V6Engine()) - - assertEquals("Vroom", car.makeSound()) - } - -} - -interface Engine { - fun makeSound(): String -} - -class V6Engine: Engine { - override fun makeSound(): String { - return "Vroom" - } -} - -class Car(e: Engine) : Engine by e \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExceptionsTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExceptionsTest.kt deleted file mode 100644 index 073c4dd890..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExceptionsTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.kotlinvsjava - -import java.io.IOException -import kotlin.test.Test -import kotlin.test.assertEquals - -class ExceptionsTest { - - @Test - fun givenATryExpression_whenReturning5InLastExpressionOfTryBlock_thenWeGet5() { - val value: Int = try { 5 } catch (e: IOException) { 6 } - - assertEquals(5, value) - } - - @Test - fun givenATryExpression_whenReturning6InLastExpressionOfCatchBlock_thenWeGet6() { - val value: Int = try { funThrowingException() } catch (e: IOException) { 6 } - - assertEquals(6, value) - } - - @org.junit.Test(expected = IllegalArgumentException::class) - fun givenANullString_whenUsingElvisOperator_thenExceptionIsThrown() { - val sampleString: String? = null - - sampleString?.length ?: throw IllegalArgumentException("String must not be null") - } - - private fun funThrowingException(): Nothing { - throw IOException() - } - -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExtensionFunctionsTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExtensionFunctionsTest.kt deleted file mode 100644 index 3db73b6d2d..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/ExtensionFunctionsTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals - -class ExtensionFunctionsTest { - - @Test - fun givenAStringWithAnExtensionFunction_whenCallingThatFunction_thenItConcatenatesStrings() { - val sampleString = "ABC" - val concatenatedString = sampleString.appendString("DEF") - - assertEquals("ABCDEF", concatenatedString) - } - - @Test - fun givenAStringWithAnExtensionProperty_whenReadingProperty_thenItReturnsLengthOfString() { - val sampleString = "ABC" - - assertEquals(3, sampleString.size) - } - - fun String.appendString(str : String): String { - return plus(str) - } - - val String.size: Int - get() = length - -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/FunctionsTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/FunctionsTest.kt deleted file mode 100644 index 6176478dfe..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/FunctionsTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals - -class FunctionsTest { - - @Test - fun givenALambdaExpressionConcatenatingString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() { - val concat: (String, String) -> String = { a, b -> a + b } - - assertEquals("AB", concat("A","B")) - } - - @Test - fun givenAnAnonymousFunctionConcatenatingString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() { - val concat: (String, String) -> String = fun(a: String, b: String): String { return a + b } - - assertEquals("AB", concat("A","B")) - } - - @Test - fun givenAnPlusMethodOfString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() { - val concat = String::plus - - assertEquals("AB", concat("A","B")) - } - - @Test - fun givenAStringConstractorAssignedToFunction_whenUsingFunctionReference_thenWeGetNewString() { - val concat = ::String - - assertEquals("A", concat().plus("A")) - } - - @Test - fun givenAClassImplementingAFunctionType_whenUsingTheFunctionWithAAndBString_thenWeGetAB() { - val concat = StringConcatenation() - - assertEquals("AB", concat("A", "B")) - } - - @Test - fun givenALambdaExpressionWithReceiver_whenUsingTheFunctionWithReceiver_thenWeGetABC() { - val concat: String.(String, String) -> String = { a, b -> plus(a).plus(b) } - - assertEquals("ABC", "A".concat("B", "C")) - } - - @Test - fun givenALambdaExpressionWithinLambdaExpression_whenUsingTheFunction_thenWeGetAB() { - val concat: (String) -> ((String) -> String) = { a -> {b -> a + b} } - - assertEquals("AB", (concat("A")("B"))) - } - - @Test - fun given3NestedLambdaExpression_whenUsingTheFunction_thenWeGetABC() { - val concat: (String) -> (String) -> (String) -> String = { a -> {b -> { c -> a + b + c} } } - - assertEquals("ABC", concat("A")("B")("C")) - } - -} - -class StringConcatenation: (String, String) -> String { - override fun invoke(p1: String, p2: String): String { - return p1 + p2 - } -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/IsOperatorTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/IsOperatorTest.kt deleted file mode 100644 index 1817602cdf..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/IsOperatorTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.math.absoluteValue -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class IsOperatorTest { - - @Test - fun givenSampleValue_whenUsingIsOperatorInIfStatement_thenItCastsAutomaticallyToString() { - val value: Any = "string" - - if(value is String) { - assertEquals(6, value.length) - } - } - - @Test - fun givenSampleValue_whenUsingIsOperatorWithAndOperator_thenItCastsAutomaticallyToString() { - val value: Any = "string" - - assertTrue(value is String && value.length == 6) - } - - @Test - fun givenSampleValue_whenUsingWithWhenOperator_thenItCastsAutomaticallyToString() { - val value: Any = "string" - - when(value) { - is String -> assertEquals(6, value.length) - is Int -> assertEquals(6, value.absoluteValue) - } - } - -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/NullSafetyTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/NullSafetyTest.kt deleted file mode 100644 index 8cb3cbc761..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/NullSafetyTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.baeldung.kotlinvsjava - -import kotlin.test.Test -import java.lang.NullPointerException -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class NullSafetyTest { - - @Test - fun givenStringAndNull_whenUsingSafeCallOperatorWithLengthMethod_thenReturnsLengthForStringAndNullForNull() { - val stringValue: String? = "string" - val nullValue: String? = null - - assertNotNull(stringValue?.length) - assertNull(nullValue?.length) - } - - @Test(expected = NullPointerException::class) - fun givenNullReference_whenUsingTheNotNullAssertionOperator_thenItThrowsNullPointerException() { - val stringValue: String? = "string" - val nullValue: String? = null - - assertNotNull(stringValue!!.length) - nullValue!!.length - } - - @Test - fun givenStringAndNull_whenUsingElvisOperator_thenItTestsAgainstNullAndReturnsTheProperValue() { - val stringValue: String? = "string" - val nullValue: String? = null - - val shouldBeLength: Int = stringValue?.length ?: -1 - val souldBeMinusOne: Int = nullValue?.length ?: -1 - - assertEquals(6, shouldBeLength) - assertEquals(-1, souldBeMinusOne) - } - - @Test - fun givenString_whenCastingToInt_thenItReturnsNull() { - val stringValue: String? = "string" - - val intValue: Int? = stringValue as? Int - - assertNull(intValue) - } - - @Test - fun givenCollectionWithNulls_whenFilterNonNull_thenItReturnsCollectionWithoutNulls() { - val list: List = listOf("a", "b", null) - val nonNullList = list.filterNotNull() - - assertEquals(2, nonNullList.size) - assertEquals(nonNullList, listOf("a", "b")) - } - - @Test - fun givenCollectionWithNulls_whenLetWithSafeCallOperator_thenItOmitsNulls() { - val list: List = listOf("a", "b", null) - for(elem in list) { - elem?.let { assertNotNull(it) } - } - } - -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/OperatorsOverloadingTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/OperatorsOverloadingTest.kt deleted file mode 100644 index a28008da20..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/OperatorsOverloadingTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class OperatorsOverloadingTest { - - @Test - fun givenThePlaneClassWithOverloadedIncrementationOperator_whenCallingTheOperator_thenItIncreasesSpeed(){ - var plane = Plane(0.0) - - plane++ - assertEquals(50.0, plane.currentSpeed) - } - - @Test - fun givenThePlaneClassWithOverloadedMinusOperator_whenCallingTheOperator_thenItDecreaseSpeed(){ - var plane = Plane(1000.0) - - plane - 500.0 - assertEquals(500.0, plane.currentSpeed) - } - - @Test - fun givenThePlaneClassWithOverloadedInvokeOperator_whenCallingTheOperator_thenItSetSpeed(){ - var plane = Plane(0.0) - - plane(150.0) - assertEquals(150.0, plane.currentSpeed) - } - - @Test - fun given2PlaneObjectWithOverloadedComparisonOperator_whenCallingTheOperator_thenItComparesSpeedValues(){ - var plane = Plane(0.0) - var plane2 = Plane(150.0) - - assertTrue(plane < (plane2)) - } - -} - -class Plane(var currentSpeed: Double) { - - operator fun inc(): Plane { - currentSpeed += 50.0 - return this - } - - operator fun minus(number: Double) { - currentSpeed = if(currentSpeed < number) 0.0 else currentSpeed - number - } - - operator fun invoke(speed: Double) { - currentSpeed = speed - } - - operator fun compareTo(plane: Plane): Int { - return currentSpeed.compareTo(plane.currentSpeed) - } -} \ No newline at end of file diff --git a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/PropertiesTest.kt b/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/PropertiesTest.kt deleted file mode 100644 index 95abcd68a2..0000000000 --- a/guest/core-kotlin/src/test/kotlin/com/baeldung/kotlinvsjava/PropertiesTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.kotlinvsjava - -import org.junit.Test -import java.math.BigDecimal -import kotlin.test.assertEquals - -class PropertiesTest { - - @Test - fun givenASampleClassWithValAndVarProperties_whenSettingPrice_thenWeGetZeroOrOne() { - val product = Product() - product.price = BigDecimal(10) - - val product2 = Product() - product2.price = null - - assertEquals("empty", product.id) - assertEquals("empty", product2.id) - assertEquals(BigDecimal(10), product.price) - assertEquals(BigDecimal(1), product2.price) - } - -} - -class Product { - - val id: String? = "empty" - - var price: BigDecimal? = BigDecimal.ZERO - set(value) = if(value == null) { field = BigDecimal.ONE} else { field = value } - -} \ No newline at end of file diff --git a/guest/deep-jsf/README.md b/guest/deep-jsf/README.md deleted file mode 100644 index b5f532535b..0000000000 --- a/guest/deep-jsf/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## Building - -To build the module, use Maven's `package` goal: - -``` -mvn clean package -``` - -The `war` file will be available at `target/deep-jsf.war` - -## Running - -The `war` application is deployed to a Java EE 7 compliant application server, for example, to GlassFish 4 or later. - -The example then will be accessible at http://localhost:8080/deep-jsf/index.xhtml \ No newline at end of file diff --git a/guest/deep-jsf/pom.xml b/guest/deep-jsf/pom.xml deleted file mode 100644 index 91cf567e73..0000000000 --- a/guest/deep-jsf/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - com.stackify - deep-jsf - 0.0.1-SNAPSHOT - deep-jsf - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - javax - javaee-api - ${javaee-api.version} - provided - - - - - deep-jsf - - - - false - 7.0 - - - \ No newline at end of file diff --git a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/GreetControllerBean.java b/guest/deep-jsf/src/main/java/com/stackify/deepjsf/GreetControllerBean.java deleted file mode 100644 index 7f5cf99781..0000000000 --- a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/GreetControllerBean.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stackify.deepjsf; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.RequestScoped; - -@ManagedBean -@RequestScoped -public class GreetControllerBean { - - public String greet() { - return "greet"; - } - -} diff --git a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/PhaseListenerBean.java b/guest/deep-jsf/src/main/java/com/stackify/deepjsf/PhaseListenerBean.java deleted file mode 100644 index d4f6a6e815..0000000000 --- a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/PhaseListenerBean.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.stackify.deepjsf; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.RequestScoped; -import javax.faces.component.UIComponent; -import javax.faces.component.UIViewRoot; -import javax.faces.component.visit.VisitContext; -import javax.faces.component.visit.VisitResult; -import javax.faces.event.PhaseEvent; -import javax.faces.event.PhaseId; -import javax.servlet.http.HttpServletRequest; - -@ManagedBean -@RequestScoped -public class PhaseListenerBean { - - public void beforeListener(PhaseEvent event) { - if (!event.getPhaseId().equals(PhaseId.RENDER_RESPONSE)) { - return; - } - UIViewRoot root = event.getFacesContext().getViewRoot(); - - boolean showNewFeature = showNewFeatureForIp(event); - - processComponentTree(root, event, showNewFeature); - } - - private boolean showNewFeatureForIp(PhaseEvent event) { - HttpServletRequest request = (HttpServletRequest) event.getFacesContext() - .getExternalContext().getRequest(); - String ip = request.getRemoteAddr(); - return !ip.startsWith("127.0"); - } - - private void processComponentTree(UIComponent component, PhaseEvent event, boolean show) { - component.visitTree(VisitContext.createVisitContext(event.getFacesContext()), - (context, target) -> { - if (target.getId() != null - && target.getId().startsWith("new-feature-") - && !show) { - target.setRendered(false); - } - return VisitResult.ACCEPT; - }); - } - -} diff --git a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserBean.java b/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserBean.java deleted file mode 100644 index f6c94e87b8..0000000000 --- a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserBean.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.stackify.deepjsf; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.SessionScoped; -import javax.faces.event.ValueChangeEvent; - -@ManagedBean -@SessionScoped -public class UserBean { - - private String name = ""; - - private String lastName = ""; - - private String proposedLogin = ""; - - public void nameChanged(ValueChangeEvent event) { - this.proposedLogin = event.getNewValue() + "-" + lastName; - } - - public void lastNameChanged(ValueChangeEvent event) { - this.proposedLogin = name + "-" + event.getNewValue(); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getProposedLogin() { - return proposedLogin; - } - - public void setProposedLogin(String proposedLogin) { - this.proposedLogin = proposedLogin; - } -} diff --git a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserControllerBean.java b/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserControllerBean.java deleted file mode 100644 index c2a46a019a..0000000000 --- a/guest/deep-jsf/src/main/java/com/stackify/deepjsf/UserControllerBean.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stackify.deepjsf; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.RequestScoped; - -@ManagedBean -@RequestScoped -public class UserControllerBean { - - public String register() { - return "register-success"; - } - -} diff --git a/guest/deep-jsf/src/main/webapp/WEB-INF/faces-config.xml b/guest/deep-jsf/src/main/webapp/WEB-INF/faces-config.xml deleted file mode 100644 index 264e60065c..0000000000 --- a/guest/deep-jsf/src/main/webapp/WEB-INF/faces-config.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - /register.xhtml - - register-success - /hello.xhtml - - - - \ No newline at end of file diff --git a/guest/deep-jsf/src/main/webapp/greet.xhtml b/guest/deep-jsf/src/main/webapp/greet.xhtml deleted file mode 100644 index 50c79c64e1..0000000000 --- a/guest/deep-jsf/src/main/webapp/greet.xhtml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/guest/deep-jsf/src/main/webapp/hello.xhtml b/guest/deep-jsf/src/main/webapp/hello.xhtml deleted file mode 100644 index f9c3745dca..0000000000 --- a/guest/deep-jsf/src/main/webapp/hello.xhtml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/guest/deep-jsf/src/main/webapp/index.xhtml b/guest/deep-jsf/src/main/webapp/index.xhtml deleted file mode 100644 index de99b89815..0000000000 --- a/guest/deep-jsf/src/main/webapp/index.xhtml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/guest/deep-jsf/src/main/webapp/register.xhtml b/guest/deep-jsf/src/main/webapp/register.xhtml deleted file mode 100644 index ba1b8e0233..0000000000 --- a/guest/deep-jsf/src/main/webapp/register.xhtml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/guest/junit5-example/.gitignore b/guest/junit5-example/.gitignore deleted file mode 100644 index 60be5b80aa..0000000000 --- a/guest/junit5-example/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -.settings/ -.classpath -.project diff --git a/guest/junit5-example/pom.xml b/guest/junit5-example/pom.xml deleted file mode 100644 index a88f739891..0000000000 --- a/guest/junit5-example/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - 4.0.0 - junit5-example - junit5-example - 0.0.1-SNAPSHOT - junit5-example - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - org.junit.jupiter - junit-jupiter-params - ${junit-jupiter.version} - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - - - com.h2database - h2 - ${h2.version} - - - org.apache.logging.log4j - log4j-core - ${log4j-core.version} - - - - - - - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit-platform-surefire-provider.version} - - - - - math - - - - - - - - 2.8.2 - - \ No newline at end of file diff --git a/guest/junit5-example/src/main/java/com/stackify/daos/UserDAO.java b/guest/junit5-example/src/main/java/com/stackify/daos/UserDAO.java deleted file mode 100644 index 091d077ef6..0000000000 --- a/guest/junit5-example/src/main/java/com/stackify/daos/UserDAO.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.stackify.daos; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import com.stackify.models.User; -import com.stackify.utils.ConnectionUtil; - -public class UserDAO { - - private Logger logger = LogManager.getLogger(UserDAO.class); - - public void createTable() { - try (Connection con = ConnectionUtil.getConnection()) { - String createQuery = "CREATE TABLE users(email varchar(50) primary key, name varchar(50))"; - PreparedStatement pstmt = con.prepareStatement(createQuery); - - pstmt.execute(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - - } - - public void add(User user) { - try (Connection con = ConnectionUtil.getConnection()) { - - String insertQuery = "INSERT INTO users(email,name) VALUES(?,?)"; - PreparedStatement pstmt = con.prepareStatement(insertQuery); - pstmt.setString(1, user.getEmail()); - pstmt.setString(2, user.getName()); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - - public void update(User user) { - try (Connection con = ConnectionUtil.getConnection()) { - - String updateQuery = "UPDATE users SET name=? WHERE email=?"; - PreparedStatement pstmt = con.prepareStatement(updateQuery); - pstmt.setString(1, user.getName()); - pstmt.setString(2, user.getEmail()); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - - public void delete(User user) { - try (Connection con = ConnectionUtil.getConnection()) { - - String deleteQuery = "DELETE FROM users WHERE email=?"; - PreparedStatement pstmt = con.prepareStatement(deleteQuery); - pstmt.setString(1, user.getEmail()); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - - public void delete(String email) { - try (Connection con = ConnectionUtil.getConnection()) { - - String deleteQuery = "DELETE FROM users WHERE email=?"; - PreparedStatement pstmt = con.prepareStatement(deleteQuery); - pstmt.setString(1, email); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - - public User findOne(String email) { - User user = null; - - try (Connection con = ConnectionUtil.getConnection()) { - String query = "SELECT * FROM users WHERE email=?"; - PreparedStatement pstmt = con.prepareStatement(query); - pstmt.setString(1, email); - - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - user = new User(); - user.setEmail(rs.getString("email")); - user.setName(rs.getString("name")); - } - - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - - return user; - } - - public List findAll() { - List users = new ArrayList<>(); - - try (Connection con = ConnectionUtil.getConnection()) { - String query = "SELECT * FROM users"; - PreparedStatement pstmt = con.prepareStatement(query); - - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - User user = new User(); - user.setEmail(rs.getString("email")); - user.setName(rs.getString("name")); - users.add(user); - } - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - - return users; - } - - public void deleteAll() { - try (Connection con = ConnectionUtil.getConnection()) { - - String deleteQuery = "DELETE FROM users"; - PreparedStatement pstmt = con.prepareStatement(deleteQuery); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - -} diff --git a/guest/junit5-example/src/main/java/com/stackify/models/User.java b/guest/junit5-example/src/main/java/com/stackify/models/User.java deleted file mode 100644 index d6951102a7..0000000000 --- a/guest/junit5-example/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.stackify.models; - -public class User { - private String email; - private String name; - - public User() { - } - - public User(String email, String name) { - super(); - this.email = email; - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((email == null) ? 0 : email.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - User other = (User) obj; - if (email == null) { - if (other.email != null) - return false; - } else if (!email.equals(other.email)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - -} diff --git a/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironment.java b/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironment.java deleted file mode 100644 index 2c1fa80f2e..0000000000 --- a/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironment.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.stackify.test.conditions; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.jupiter.api.extension.ExtendWith; - -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@ExtendWith(DisabledOnEnvironmentCondition.class) -public @interface DisabledOnEnvironment { - String[] value(); -} \ No newline at end of file diff --git a/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironmentCondition.java b/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironmentCondition.java deleted file mode 100644 index adb9d9c09e..0000000000 --- a/guest/junit5-example/src/main/java/com/stackify/test/conditions/DisabledOnEnvironmentCondition.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.test.conditions; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Optional; -import java.util.Properties; - -import org.junit.jupiter.api.extension.ConditionEvaluationResult; -import org.junit.jupiter.api.extension.TestExecutionCondition; -import org.junit.jupiter.api.extension.TestExtensionContext; -import org.junit.platform.commons.support.AnnotationSupport; - -import com.stackify.utils.ConnectionUtil; - -public class DisabledOnEnvironmentCondition implements TestExecutionCondition { - - @Override - public ConditionEvaluationResult evaluate(TestExtensionContext context) { - Properties props = new Properties(); - String env = ""; - try { - props.load(ConnectionUtil.class.getResourceAsStream("/application.properties")); - env = props.getProperty("env"); - } catch (IOException e) { - e.printStackTrace(); - } - Optional disabled = AnnotationSupport.findAnnotation(context.getElement().get(), DisabledOnEnvironment.class); - if (disabled.isPresent()) { - String[] envs = disabled.get().value(); - if (Arrays.asList(envs).contains(env)) { - return ConditionEvaluationResult.disabled("Disabled on environment " + env); - } - } - - return ConditionEvaluationResult.enabled("Enabled on environment "+env); - } - -} diff --git a/guest/junit5-example/src/main/java/com/stackify/utils/ConnectionUtil.java b/guest/junit5-example/src/main/java/com/stackify/utils/ConnectionUtil.java deleted file mode 100644 index bcfe5058a7..0000000000 --- a/guest/junit5-example/src/main/java/com/stackify/utils/ConnectionUtil.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.utils; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Properties; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class ConnectionUtil { - - private static Logger logger = LogManager.getLogger(ConnectionUtil.class); - - public static Connection getConnection() { - try { - Properties props = new Properties(); - props.load(ConnectionUtil.class.getResourceAsStream("jdbc.properties")); - Class.forName(props.getProperty("jdbc.driver")); - Connection con = DriverManager.getConnection(props.getProperty("jdbc.url"), props.getProperty("jdbc.user"), props.getProperty("jdbc.password")); - return con; - } - - catch (FileNotFoundException exc) { - logger.error(exc.getMessage()); - } catch (IOException exc) { - logger.error(exc.getMessage()); - } catch (ClassNotFoundException exc) { - logger.error(exc.getMessage()); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - return null; - } - -} diff --git a/guest/junit5-example/src/main/resources/application.properties b/guest/junit5-example/src/main/resources/application.properties deleted file mode 100644 index 601f964ff3..0000000000 --- a/guest/junit5-example/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -env=dev \ No newline at end of file diff --git a/guest/junit5-example/src/main/resources/com/stackify/utils/jdbc.properties b/guest/junit5-example/src/main/resources/com/stackify/utils/jdbc.properties deleted file mode 100644 index 2d9a39b157..0000000000 --- a/guest/junit5-example/src/main/resources/com/stackify/utils/jdbc.properties +++ /dev/null @@ -1,4 +0,0 @@ -jdbc.driver=org.h2.Driver -jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 -jdbc.user= -jdbc.password= \ No newline at end of file diff --git a/guest/junit5-example/src/main/resources/log4j2.xml b/guest/junit5-example/src/main/resources/log4j2.xml deleted file mode 100644 index 602b5ab490..0000000000 --- a/guest/junit5-example/src/main/resources/log4j2.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/junit5-example/src/test/java/com/stackify/test/DatabaseConnectionTest.java b/guest/junit5-example/src/test/java/com/stackify/test/DatabaseConnectionTest.java deleted file mode 100644 index d8f13b5715..0000000000 --- a/guest/junit5-example/src/test/java/com/stackify/test/DatabaseConnectionTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.stackify.test; - -import java.sql.Connection; - -import org.junit.jupiter.api.Test; - -import com.stackify.utils.ConnectionUtil; - -import static org.junit.jupiter.api.Assertions.*; - -public interface DatabaseConnectionTest { - - @Test - default void testDatabaseConnection() { - Connection con = ConnectionUtil.getConnection(); - assertNotNull(con); - } - -} diff --git a/guest/junit5-example/src/test/java/com/stackify/test/DynamicTests.java b/guest/junit5-example/src/test/java/com/stackify/test/DynamicTests.java deleted file mode 100644 index 39b3b5aac5..0000000000 --- a/guest/junit5-example/src/test/java/com/stackify/test/DynamicTests.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.test; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.TestFactory; -import org.junit.jupiter.api.function.ThrowingConsumer; - -import com.stackify.daos.UserDAO; -import com.stackify.models.User; - -public class DynamicTests { - - @TestFactory - public Collection dynamicTestCollection() { - return Arrays.asList(DynamicTest.dynamicTest("Dynamic Test", () -> assertTrue(1 == 1))); - } - - @TestFactory - public Stream dynamicUserTestCollection() { - List inputList = Arrays.asList(new User("john@yahoo.com", "John"), new User("ana@yahoo.com", "Ana")); - - Function displayNameGenerator = (input) -> "Saving user: " + input; - - UserDAO userDAO = new UserDAO(); - ThrowingConsumer testExecutor = (input) -> { - userDAO.add(input); - assertNotNull(userDAO.findOne(input.getEmail())); - }; - - return DynamicTest.stream(inputList.iterator(), displayNameGenerator, testExecutor); - } -} diff --git a/guest/junit5-example/src/test/java/com/stackify/test/IncrementTest.java b/guest/junit5-example/src/test/java/com/stackify/test/IncrementTest.java deleted file mode 100644 index a23a5bf20b..0000000000 --- a/guest/junit5-example/src/test/java/com/stackify/test/IncrementTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.stackify.test; - -import static org.junit.jupiter.api.Assertions.*; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.RepetitionInfo; - -public class IncrementTest { - - private static Logger logger = LogManager.getLogger(IncrementTest.class); - - @BeforeEach - public void increment() { - logger.info("Before Each Test"); - } - - @RepeatedTest(value = 3, name = RepeatedTest.SHORT_DISPLAY_NAME) - public void test(RepetitionInfo info) { - assertTrue(1 == 1); - logger.info("Repetition #" + info.getCurrentRepetition()); - } -} diff --git a/guest/junit5-example/src/test/java/com/stackify/test/TaggedTest.java b/guest/junit5-example/src/test/java/com/stackify/test/TaggedTest.java deleted file mode 100644 index db3c38ceac..0000000000 --- a/guest/junit5-example/src/test/java/com/stackify/test/TaggedTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.stackify.test; - -import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -@Tag("math") -public class TaggedTest { - - @Test - @Tag("arithmetic") - public void testEquals() { - assertTrue(1 == 1); - } - -} diff --git a/guest/junit5-example/src/test/java/com/stackify/test/UsersTest.java b/guest/junit5-example/src/test/java/com/stackify/test/UsersTest.java deleted file mode 100644 index 88958a8232..0000000000 --- a/guest/junit5-example/src/test/java/com/stackify/test/UsersTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.stackify.test; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assumptions.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.stackify.daos.UserDAO; -import com.stackify.models.User; - -import com.stackify.test.conditions.DisabledOnEnvironment; - -public class UsersTest implements DatabaseConnectionTest { - - private static UserDAO userDAO; - - private static Logger logger = LogManager.getLogger(UsersTest.class); - - @BeforeAll - public static void addData() { - userDAO = new UserDAO(); - userDAO.createTable(); - - User user1 = new User("john@gmail.com", "John"); - User user2 = new User("ana@gmail.com", "Ana"); - userDAO.add(user1); - userDAO.add(user2); - } - - @Test - @DisplayName("Test Get Users") - public void testGetUsersNumber() { - assertEquals(2, userDAO.findAll().size()); - - } - - @Test - @DisplayName("Test Get Users") - public void testGetUsersNumberWithInfo(TestInfo testInfo) { - assertEquals(2, userDAO.findAll().size()); - assertEquals("Test Get Users", testInfo.getDisplayName()); - assertEquals(UsersTest.class, testInfo.getTestClass().get()); - logger.info("Running test method:" + testInfo.getTestMethod().get().getName()); - } - - @Test - public void testGetUser() { - User user = userDAO.findOne("john@gmail.com"); - assertEquals("John", user.getName(), "User name:" + user.getName() + " incorrect"); - } - - @Test - public void testClassicAssertions() { - User user1 = userDAO.findOne("john@gmail.com"); - User user2 = userDAO.findOne("john@yahoo.com"); - - assertNotNull(user1); - assertNull(user2); - - user2 = new User("john@yahoo.com", "John"); - assertEquals(user1.getName(), user2.getName(), "Names are not equal"); - assertFalse(user1.getEmail().equals(user2.getEmail()), "Emails are equal"); - assertNotSame(user1, user2); - } - - @Test - @Disabled - public void testGroupedAssertions() { - User user = userDAO.findOne("john@gmail.com"); - assertAll("user", () -> assertEquals("Johnson", user.getName()), () -> assertEquals("johnson@gmail.com", user.getEmail())); - } - - @Test - public void testIterableEquals() { - User user1 = new User("john@gmail.com", "John"); - User user2 = new User("ana@gmail.com", "Ana"); - - List users = new ArrayList<>(); - users.add(user1); - users.add(user2); - - assertIterableEquals(users, userDAO.findAll()); - } - - @Test - public void testLinesMatch() { - List expectedLines = Collections.singletonList("(.*)@(.*)"); - List emails = Arrays.asList("john@gmail.com"); - assertLinesMatch(expectedLines, emails); - } - - @Test - void testThrows() { - User user = null; - Exception exception = assertThrows(NullPointerException.class, () -> user.getName()); - logger.info(exception.getMessage()); - } - - @Test - @DisabledOnEnvironment({ "dev", "prod") - void testFail() { - fail("this test fails"); - } - - @Test - void testAssumptions() { - List users = userDAO.findAll(); - assumeFalse(users == null); - assumeTrue(users.size() > 0); - - User user1 = new User("john@gmail.com", "John"); - - assumingThat(users.contains(user1), () -> assertTrue(users.size() > 1)); - } - - @ParameterizedTest - @ValueSource(strings = { "john@gmail.com", "ana@gmail.com" }) - public void testParameterized(String email) { - assertNotNull(userDAO.findOne(email)); - } - - @AfterAll - public static void removeData() { - userDAO.deleteAll(); - } - - @Nested - class DeleteUsersTest { - @Test - public void addUser() { - User user = new User("bob@gmail.com", "Bob"); - userDAO.add(user); - assertNotNull(userDAO.findOne("bob@gmail.com")); - - userDAO.delete("bob@gmail.com"); - assertNull(userDAO.findOne("bob@gmail.com")); - } - } - -} diff --git a/guest/log4j2-example/.gitignore b/guest/log4j2-example/.gitignore deleted file mode 100644 index 60be5b80aa..0000000000 --- a/guest/log4j2-example/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -.settings/ -.classpath -.project diff --git a/guest/log4j2-example/java.log b/guest/log4j2-example/java.log deleted file mode 100644 index 21e964d9ce..0000000000 --- a/guest/log4j2-example/java.log +++ /dev/null @@ -1,3 +0,0 @@ -14:00:35.258 INFO Programmatic Logger Message -14:03:51.178 INFO Programmatic Logger Message -14:04:11.753 INFO Programmatic Logger Message diff --git a/guest/log4j2-example/logs/app.log b/guest/log4j2-example/logs/app.log deleted file mode 100644 index 022f6fcea9..0000000000 --- a/guest/log4j2-example/logs/app.log +++ /dev/null @@ -1,25 +0,0 @@ -[ -{ - "timeMillis" : 1496315051753, - "thread" : "main", - "level" : "INFO", - "loggerName" : "RollingFileLogger", - "message" : "Json Message 1", - "endOfBatch" : false, - "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger", - "threadId" : 1, - "threadPriority" : 5 -} -, { - "timeMillis" : 1496315051862, - "thread" : "main", - "level" : "INFO", - "loggerName" : "RollingFileLogger", - "message" : "Json Messag 2", - "endOfBatch" : false, - "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger", - "threadId" : 1, - "threadPriority" : 5 -} - -] diff --git a/guest/log4j2-example/pom.xml b/guest/log4j2-example/pom.xml deleted file mode 100644 index a3284dbfe3..0000000000 --- a/guest/log4j2-example/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - 4.0.0 - log4j2-example - log4j2-example - 0.0.1-SNAPSHOT - log4j2-example - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - - org.apache.logging.log4j - log4j-core - ${log4j-core.version} - - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - - - - - src/main/resources/ - - **/*.java - - - - - - - 2.8.2 - - - \ No newline at end of file diff --git a/guest/log4j2-example/src/main/java/com/stackify/models/User.java b/guest/log4j2-example/src/main/java/com/stackify/models/User.java deleted file mode 100644 index 1a53651292..0000000000 --- a/guest/log4j2-example/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.stackify.models; - -import java.time.LocalDate; - -public class User { - private String name; - private String email; - private LocalDate dateOfBirth; - - public User() { - } - - public User(String name, String email) { - super(); - this.name = name; - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public LocalDate getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(LocalDate dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } - -} diff --git a/guest/log4j2-example/src/main/java/com/stackify/services/MyService.java b/guest/log4j2-example/src/main/java/com/stackify/services/MyService.java deleted file mode 100644 index 4b1dc0bf34..0000000000 --- a/guest/log4j2-example/src/main/java/com/stackify/services/MyService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stackify.services; - -import java.time.LocalDate; -import java.time.Period; - -import com.stackify.models.User; - -public class MyService { - - public int calculateUserAge(User user) { - return Period.between(user.getDateOfBirth(), LocalDate.now()).getYears(); - } - -} diff --git a/guest/log4j2-example/src/main/resources/log4j2.xml b/guest/log4j2-example/src/main/resources/log4j2.xml deleted file mode 100644 index 06f2ba5245..0000000000 --- a/guest/log4j2-example/src/main/resources/log4j2.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/log4j2-example/src/test/java/com/stackify/services/MyServiceUnitTest.java b/guest/log4j2-example/src/test/java/com/stackify/services/MyServiceUnitTest.java deleted file mode 100644 index bd08225be4..0000000000 --- a/guest/log4j2-example/src/test/java/com/stackify/services/MyServiceUnitTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.stackify.services; - -import java.time.LocalDate; -import java.time.Month; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.appender.FileAppender; -import org.apache.logging.log4j.core.config.AppenderRef; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.LoggerConfig; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.junit.Test; - -import com.stackify.models.User; -import com.stackify.services.MyService; - -public class MyServiceUnitTest { - - private static final Logger logger = LogManager.getLogger(MyServiceUnitTest.class); - - @Test - public void testService() { - MyService myService = new MyService(); - User user = new User("John", "john@yahoo.com"); - user.setDateOfBirth(LocalDate.of(1980, Month.APRIL, 20)); - logger.info("Age of user {} is {}", () -> user.getName(), () -> myService.calculateUserAge(user)); - } - - @Test - public void testColoredLogger() { - logger.fatal("Fatal level message"); - logger.error("Error level message"); - logger.warn("Warn level message"); - logger.info("Info level message"); - logger.debug("Debug level message"); - } - - @Test - public void testRollingFileAppender() { - Logger rfLogger = LogManager.getLogger("RollingFileLogger"); - rfLogger.info("Json Message 1"); - rfLogger.info("Json Message 2"); - } - - @Test - public void testProgrammaticConfig() { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - - PatternLayout layout = PatternLayout.newBuilder().withConfiguration(config).withPattern("%d{HH:mm:ss.SSS} %level %msg%n").build(); - - Appender appender = FileAppender.newBuilder().setConfiguration(config).withName("programmaticFileAppender").withLayout(layout).withFileName("java.log").build(); - appender.start(); - config.addAppender(appender); - AppenderRef ref = AppenderRef.createAppenderRef("programmaticFileAppender", null, null); - AppenderRef[] refs = new AppenderRef[] { ref }; - - LoggerConfig loggerConfig = LoggerConfig.createLogger(false, Level.INFO, "programmaticLogger", "true", refs, null, config, null); - - loggerConfig.addAppender(appender, null, null); - config.addLogger("programmaticLogger", loggerConfig); - ctx.updateLoggers(); - - Logger pLogger = LogManager.getLogger("programmaticLogger"); - pLogger.info("Programmatic Logger Message"); - } - - @Test - public void testCustomLevel() { - Level myLevel = Level.forName("NEW_LEVEL", 350); - logger.log(myLevel, "Custom Level Message"); - - logger.log(Level.getLevel("NEW_XML_LEVEL"), "Custom XML Level Message"); - - } - -} diff --git a/guest/logback-example/src/main/java/com/stackify/logging/IgnoreLoggerFilter.java b/guest/logback-example/src/main/java/com/stackify/logging/IgnoreLoggerFilter.java deleted file mode 100644 index c0eb414588..0000000000 --- a/guest/logback-example/src/main/java/com/stackify/logging/IgnoreLoggerFilter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stackify.logging; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.core.spi.FilterReply; - -public class IgnoreLoggerFilter extends TurboFilter { - - private String loggerName; - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { - if (loggerName == null) { - return FilterReply.NEUTRAL; - } else if (loggerName.equals(logger.getName())) { - return FilterReply.DENY; - } else - return FilterReply.NEUTRAL; - } - - public void setLoggerName(String loggerName) { - this.loggerName = loggerName; - } - -} diff --git a/guest/logback-example/src/main/java/com/stackify/models/Employee.java b/guest/logback-example/src/main/java/com/stackify/models/Employee.java deleted file mode 100644 index 1d040b372b..0000000000 --- a/guest/logback-example/src/main/java/com/stackify/models/Employee.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.stackify.models; - -public class Employee { - - private String email; - private String name; - - private double salary; - - public Employee() { - } - - public Employee(String email, String name, double salary) { - this.email = email; - this.name = name; - this.salary = salary; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getSalary() { - return salary; - } - - public void setSalary(double salary) { - this.salary = salary; - } - -} diff --git a/guest/logback-example/src/main/java/com/stackify/services/EmployeeService.java b/guest/logback-example/src/main/java/com/stackify/services/EmployeeService.java deleted file mode 100644 index 1795101f40..0000000000 --- a/guest/logback-example/src/main/java/com/stackify/services/EmployeeService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.stackify.services; - -import com.stackify.models.Employee; - -public class EmployeeService { - - public double calculateBonus(Employee user) { - return 0.1 * user.getSalary(); - } - -} diff --git a/guest/logback-example/src/main/resources/application.properties b/guest/logback-example/src/main/resources/application.properties deleted file mode 100644 index 601f964ff3..0000000000 --- a/guest/logback-example/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -env=dev \ No newline at end of file diff --git a/guest/logback-example/src/main/resources/logback.xml b/guest/logback-example/src/main/resources/logback.xml deleted file mode 100644 index d8ec24c7c3..0000000000 --- a/guest/logback-example/src/main/resources/logback.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - - System.out - - - - - - - - - log-%d{yyyy-MM-dd}.log - 30 - 3GB - - - 3MB - - - %d [%thread] %-5level %logger{50} - %msg%n - - - - - - userRole - ANONYMOUS - - - - ${userRole}.log - - %d [%thread] %level %mdc %logger{50} - %msg%n - - - - - - - - - %d %green([%thread]) %highlight(%level) %logger{50} - %msg%n - - - - - - - %thread%level%logger%msg - - - log.html - - - - - - ERROR - ACCEPT - DENY - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - - System.err - - - - - WARN - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - - - - - - - return (level > DEBUG && message.toLowerCase().contains("employee")); - - DENY - NEUTRAL - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - - - - - - 2 - - - - ignoredColorLogger - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/logback-example/src/test/java/com/stackify/services/EmployeeServiceUnitTest.java b/guest/logback-example/src/test/java/com/stackify/services/EmployeeServiceUnitTest.java deleted file mode 100644 index a3051f7087..0000000000 --- a/guest/logback-example/src/test/java/com/stackify/services/EmployeeServiceUnitTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.stackify.services; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import com.stackify.models.Employee; - -import ch.qos.logback.classic.Level; - -public class EmployeeServiceUnitTest { - private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - - private EmployeeService employeeService = new EmployeeService(); - - @Test - public void testAppenders() { - Logger rollingFileLogger = LoggerFactory.getLogger("rollingFileLogger"); - rollingFileLogger.info("Testing rolling file logger"); - - MDC.put("userRole", "ADMIN"); - Logger siftingLogger = LoggerFactory.getLogger("roleSiftingLogger"); - siftingLogger.info("Admin Action"); - } - - @Test - public void testLayouts() { - Logger htmlLogger = LoggerFactory.getLogger("htmlLogger"); - htmlLogger.error("Employee Information Update Failed"); - htmlLogger.info("New Account Created"); - - Logger colorLogger = LoggerFactory.getLogger("colorLogger"); - colorLogger.error("Employee Information Update Failed"); - colorLogger.info("New Account Created"); - } - - @Test - public void testLogLevel() { - ch.qos.logback.classic.Logger rollingFileLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("rollingFileLogger"); - rollingFileLogger.setLevel(Level.DEBUG); - rollingFileLogger.debug("Testing Log Level"); - } - - @Test - public void testParameter() { - Employee employee = new Employee("john@gmail.com", "John", 2000); - if (logger.isDebugEnabled()) { - logger.debug("The bonus for employee: " + employee.getName() + " is " + employeeService.calculateBonus(employee)); - } - logger.debug("The bonus for employee {} is {}", employee.getName(), employeeService.calculateBonus(employee)); - } - - @Test - public void testFilters() { - Logger levelFilterLogger = LoggerFactory.getLogger("levelFilterLogger"); - levelFilterLogger.error("Employee Information Update Failed"); - Logger thresholdFilterLogger = LoggerFactory.getLogger("thresholdFilterLogger"); - thresholdFilterLogger.trace("Employee record inserted"); - Logger evaluatorFilterLogger = LoggerFactory.getLogger("evaluatorFilterLogger"); - evaluatorFilterLogger.debug("Employee account deactivated"); - } - - @Test - public void testIgnoredLogger() { - Logger colorLogger = LoggerFactory.getLogger("ignoredColorLogger"); - colorLogger.info("Ignored Log Message"); - } - - @Test - public void testConditionalConfiguration() { - logger.trace("Employee record updated"); - } -} diff --git a/guest/remote-debugging/README.md b/guest/remote-debugging/README.md deleted file mode 100644 index cc63e7fd59..0000000000 --- a/guest/remote-debugging/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Building - -To build the module, use Maven's `package` goal: - -``` -mvn clean package -``` - -The `war` file will be available at `target/remote-debugging.war` - -## Running - -The `war` application is deployed to Apache Tomcat 8 or any other Java Web or Application server. -To deploy it to the Apache Tomcat 8 server, drop it in the `tomcat/webapps` directory. - -The service then will be accessible at http://localhost:8080/remote-debugging/hello?name=John \ No newline at end of file diff --git a/guest/remote-debugging/src/main/java/com/stackify/debug/config/WebInitializer.java b/guest/remote-debugging/src/main/java/com/stackify/debug/config/WebInitializer.java deleted file mode 100644 index b69e2b6c77..0000000000 --- a/guest/remote-debugging/src/main/java/com/stackify/debug/config/WebInitializer.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.stackify.debug.config; - -import com.stackify.debug.JavaRemoteDebuggingApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; - -public class WebInitializer extends SpringBootServletInitializer { - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(JavaRemoteDebuggingApplication.class); - } -} diff --git a/guest/remote-debugging/src/main/java/com/stackify/debug/rest/HelloController.java b/guest/remote-debugging/src/main/java/com/stackify/debug/rest/HelloController.java deleted file mode 100644 index 8c614a36ec..0000000000 --- a/guest/remote-debugging/src/main/java/com/stackify/debug/rest/HelloController.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.stackify.debug.rest; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController("/hello") -public class HelloController { - - @GetMapping - public String hello(@RequestParam("name") String name) { - String message = "Hello, " + name; - return message; - } - -} diff --git a/guest/slf4j/guide/pom.xml b/guest/slf4j/guide/pom.xml deleted file mode 100644 index 8b479a4ba7..0000000000 --- a/guest/slf4j/guide/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - 4.0.0 - com.stackify.slf4j.guide - slf4j-parent-module - 1.0.0-SNAPSHOT - slf4j-parent-module - pom - - - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - - - slf4j-logback - slf4j-log4j2 - slf4j-log4j - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - UTF-8 - UTF-8 - 1.8 - 2.0.0-beta.5 - - diff --git a/guest/slf4j/guide/slf4j-log4j/pom.xml b/guest/slf4j/guide/slf4j-log4j/pom.xml deleted file mode 100644 index 70b93d8ab4..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - slf4j-log4j - 0.0.1-SNAPSHOT - slf4j-log4j - jar - - - com.stackify.slf4j.guide - slf4j-parent-module - 1.0.0-SNAPSHOT - .. - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - - - org.slf4j - slf4j-log4j12 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - 1.7.25 - - diff --git a/guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java b/guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java deleted file mode 100644 index 14f4439545..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class SimpleController { - - Logger logger = LoggerFactory.getLogger(SimpleController.class); - - @GetMapping("/slf4j-guide-request") - public String processList(List list) { - logger.info("Client requested process the following list: {}", list); - try { - logger.debug("Starting process"); - // ...processing list here... - Thread.sleep(500); - } catch (RuntimeException | InterruptedException e) { - logger.error("There was an issue processing the list.", e); - } finally { - logger.info("Finished processing"); - } - return "done"; - } - - @GetMapping("/slf4j-guide-mdc-request") - public String clientMDCRequest(@RequestHeader String clientId) throws InterruptedException { - MDC.put("clientId", clientId); - logger.info("Client {} has made a request", clientId); - logger.info("Starting request"); - Thread.sleep(500); - logger.info("Finished request"); - MDC.clear(); - return "finished"; - } -} diff --git a/guest/slf4j/guide/slf4j-log4j/src/main/resources/log4j.xml b/guest/slf4j/guide/slf4j-log4j/src/main/resources/log4j.xml deleted file mode 100644 index ea432bff77..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/src/main/resources/log4j.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java b/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java deleted file mode 100644 index 991a1e2686..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import static org.powermock.api.mockito.PowerMockito.doNothing; -import static org.powermock.api.mockito.PowerMockito.spy; - -import java.util.Collections; - -import org.apache.log4j.Level; -import org.apache.log4j.spi.LoggingEvent; -import org.assertj.core.api.Condition; -import org.assertj.core.api.SoftAssertions; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.MDC; - -import com.stackify.slf4j.guide.utils.ListAppender; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(MDC.class) -public class SimpleControllerIntegrationTest { - - private SimpleController controller = new SimpleController(); - - @Before - public void clearLogList() { - ListAppender.clearEventList(); - } - - @Test - public void whenSimpleRequestMade_thenAllRegularMessagesLogged() { - String output = controller.processList(Collections.emptyList()); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("Client requested process the following list: []", Level.INFO)) - .haveAtLeastOne(eventContains("Starting process", Level.DEBUG)) - .haveAtLeastOne(eventContains("Finished processing", Level.INFO)) - .haveExactly(0, eventOfLevel(Level.ERROR)); - errorCollector.assertThat(output) - .isEqualTo("done"); - errorCollector.assertAll(); - } - - @Test - public void givenClientId_whenMDCRequestMade_thenMessagesWithClientIdLogged() throws Exception { - // We avoid cleaning the context so tht we can check it afterwards - spy(MDC.class); - doNothing().when(MDC.class); - MDC.clear(); - String clientId = "id-1234"; - - String output = controller.clientMDCRequest(clientId); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .allMatch(entry -> { - return clientId.equals(entry.getMDC("clientId")); - }) - .haveAtLeastOne(eventContains("Client id-1234 has made a request", Level.INFO)) - .haveAtLeastOne(eventContains("Starting request", Level.INFO)) - .haveAtLeastOne(eventContains("Finished request", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - - } - - private Condition eventOfLevel(Level level) { - return eventContains(null, level); - } - - private Condition eventContains(String substring, Level level) { - - return new Condition(entry -> (substring == null || (entry.getRenderedMessage() != null && entry.getRenderedMessage() - .contains(substring))) && (level == null || level.equals(entry.getLevel())), String.format("entry with message '%s', level %s", substring, level)); - } -} diff --git a/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java b/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java deleted file mode 100644 index 4ce9e73d6d..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.stackify.slf4j.guide.utils; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.AppenderSkeleton; -import org.apache.log4j.spi.LoggingEvent; - -public class ListAppender extends AppenderSkeleton { - public static List events = new ArrayList(); - - @Override - public void close() { - } - - @Override - public boolean requiresLayout() { - return false; - } - - @Override - protected void append(LoggingEvent event) { - events.add(event); - } - - public static List getEvents() { - return events; - } - - public static void clearEventList() { - events.clear(); - } -} diff --git a/guest/slf4j/guide/slf4j-log4j/src/test/resources/log4j.xml b/guest/slf4j/guide/slf4j-log4j/src/test/resources/log4j.xml deleted file mode 100644 index 10443e5eab..0000000000 --- a/guest/slf4j/guide/slf4j-log4j/src/test/resources/log4j.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-log4j2/pom.xml b/guest/slf4j/guide/slf4j-log4j2/pom.xml deleted file mode 100644 index 93a8d9e974..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - slf4j-log4j2 - 0.0.1-SNAPSHOT - slf4j-log4j2 - jar - - - com.stackify.slf4j.guide - slf4j-parent-module - 1.0.0-SNAPSHOT - .. - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - - - org.springframework.boot - spring-boot-starter-log4j2 - - - org.springframework.boot - spring-boot-starter-test - test - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - test-jar - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - test-jar - - - - - 2.11.0 - - diff --git a/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/Application.java b/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/Application.java deleted file mode 100644 index 01ccf519b3..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/Application.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.stackify.slf4j.guide; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java b/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java deleted file mode 100644 index 14f4439545..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class SimpleController { - - Logger logger = LoggerFactory.getLogger(SimpleController.class); - - @GetMapping("/slf4j-guide-request") - public String processList(List list) { - logger.info("Client requested process the following list: {}", list); - try { - logger.debug("Starting process"); - // ...processing list here... - Thread.sleep(500); - } catch (RuntimeException | InterruptedException e) { - logger.error("There was an issue processing the list.", e); - } finally { - logger.info("Finished processing"); - } - return "done"; - } - - @GetMapping("/slf4j-guide-mdc-request") - public String clientMDCRequest(@RequestHeader String clientId) throws InterruptedException { - MDC.put("clientId", clientId); - logger.info("Client {} has made a request", clientId); - logger.info("Starting request"); - Thread.sleep(500); - logger.info("Finished request"); - MDC.clear(); - return "finished"; - } -} diff --git a/guest/slf4j/guide/slf4j-log4j2/src/main/resources/application.properties b/guest/slf4j/guide/slf4j-log4j2/src/main/resources/application.properties deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/guest/slf4j/guide/slf4j-log4j2/src/main/resources/log4j2-spring.xml b/guest/slf4j/guide/slf4j-log4j2/src/main/resources/log4j2-spring.xml deleted file mode 100644 index 7d1494c7a6..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/src/main/resources/log4j2-spring.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - ???? - %5p - yyyy-MM-dd HH:mm:ss.SSS - %clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} - %clr{---}{faint} %clr{%X{clientId}}{red}%clr{@%15.15t}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-log4j2/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java b/guest/slf4j/guide/slf4j-log4j2/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java deleted file mode 100644 index f41c857533..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import java.util.Collections; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.apache.logging.log4j.test.appender.ListAppender; -import org.assertj.core.api.Condition; -import org.assertj.core.api.SoftAssertions; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; - -public class SimpleControllerIntegrationTest { - - private static ListAppender appender; - private SimpleController controller = new SimpleController(); - - @ClassRule - public static LoggerContextRule init = new LoggerContextRule("log4j2-test.xml"); - - @BeforeClass - public static void setupLogging() { - appender = init.getListAppender("ListAppender"); - } - - @Before - public void clearAppender() { - appender.clear(); - } - - @Test - public void whenSimpleRequestMade_thenAllRegularMessagesLogged() { - String output = controller.processList(Collections.emptyList()); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(appender.getEvents()) - .haveAtLeastOne(eventContains("Client requested process the following list: []", Level.INFO)) - .haveAtLeastOne(eventContains("Starting process", Level.DEBUG)) - .haveAtLeastOne(eventContains("Finished processing", Level.INFO)) - .haveExactly(0, eventOfLevel(Level.ERROR)); - errorCollector.assertThat(output) - .isEqualTo("done"); - errorCollector.assertAll(); - } - - @Test - public void givenClientId_whenMDCRequestMade_thenMessagesWithClientIdLogged() throws Exception { - String clientId = "id-1234"; - - String output = controller.clientMDCRequest(clientId); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(appender.getEvents()) - .allMatch(entry -> { - return clientId.equals(entry.getContextData() - .getValue("clientId")); - }) - .haveAtLeastOne(eventContains("Client id-1234 has made a request", Level.INFO)) - .haveAtLeastOne(eventContains("Starting request", Level.INFO)) - .haveAtLeastOne(eventContains("Finished request", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - private Condition eventOfLevel(Level level) { - return eventContains(null, level); - } - - private Condition eventContains(String substring, Level level) { - - return new Condition(entry -> (substring == null || (entry.getMessage() - .getFormattedMessage() != null && entry.getMessage() - .getFormattedMessage() - .contains(substring))) - && (level == null || level.equals(entry.getLevel())), String.format("entry with message '%s', level %s", substring, level)); - } -} diff --git a/guest/slf4j/guide/slf4j-log4j2/src/test/resources/log4j2-test.xml b/guest/slf4j/guide/slf4j-log4j2/src/test/resources/log4j2-test.xml deleted file mode 100644 index 2ca386f7f6..0000000000 --- a/guest/slf4j/guide/slf4j-log4j2/src/test/resources/log4j2-test.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/.gitignore b/guest/slf4j/guide/slf4j-logback/.gitignore deleted file mode 100644 index 82eca336e3..0000000000 --- a/guest/slf4j/guide/slf4j-logback/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/build/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/pom.xml b/guest/slf4j/guide/slf4j-logback/pom.xml deleted file mode 100644 index 74f4470bad..0000000000 --- a/guest/slf4j/guide/slf4j-logback/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - slf4j-logback - 0.0.1-SNAPSHOT - slf4j-logback - jar - - - com.stackify.slf4j.guide - slf4j-parent-module - 1.0.0-SNAPSHOT - .. - - - - - org.slf4j - slf4j-ext - - - ch.qos.cal10n - cal10n-api - ${cal10n.version} - - - - - 0.8.1 - - diff --git a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java b/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java deleted file mode 100644 index 1fab675c94..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/controllers/SimpleController.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; -import org.slf4j.cal10n.LocLogger; -import org.slf4j.cal10n.LocLoggerFactory; -import org.slf4j.ext.EventData; -import org.slf4j.ext.EventLogger; -import org.slf4j.profiler.Profiler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.stackify.slf4j.guide.l10n.Messages; - -import ch.qos.cal10n.IMessageConveyor; -import ch.qos.cal10n.MessageConveyor; - -@RestController -public class SimpleController { - - Logger logger = LoggerFactory.getLogger(SimpleController.class); - - @GetMapping("/slf4j-guide-request") - public String processList(List list) { - logger.info("Client requested process the following list: {}", list); - try { - logger.debug("Starting process"); - // ...processing list here... - Thread.sleep(500); - } catch (RuntimeException | InterruptedException e) { - logger.error("There was an issue processing the list.", e); - } finally { - logger.info("Finished processing"); - } - return "done"; - } - - @GetMapping("/slf4j-guide-mdc-request") - public String clientMDCRequest(@RequestHeader String clientId) throws InterruptedException { - MDC.put("clientId", clientId); - logger.info("Client {} has made a request", clientId); - logger.info("Starting request"); - Thread.sleep(500); - logger.info("Finished request"); - MDC.clear(); - return "finished"; - } - - @GetMapping("/slf4j-guide-marker-request") - public String clientMarkerRequest() throws InterruptedException { - logger.info("client has made a request"); - Marker myMarker = MarkerFactory.getMarker("MYMARKER"); - logger.info(myMarker, "Starting request"); - Thread.sleep(500); - logger.debug(myMarker, "Finished request"); - return "finished"; - } - - @GetMapping("/slf4j-guide-profiler-request") - public String clientProfilerRequest() { - logger.info("client has made a request"); - Profiler myProfiler = new Profiler("MYPROFILER"); - // Associate the logger to handle the output( for testing purposes here) - myProfiler.setLogger(logger); - - myProfiler.start("List generation process"); - List list = generateList(); - - myProfiler.start("List sorting process"); - Collections.sort(list); - - // Use the log() method instead of print() to use the logger (for testing purposes here) - myProfiler.stop() - .log(); - return "finished"; - } - - private List generateList() { - List generated = new ArrayList<>(); - for (int i = 0; i < 5000; i++) { - generated.add(ThreadLocalRandom.current() - .nextInt(2000)); - } - return generated; - } - - @GetMapping("/slf4j-guide-event-request") - public String clientEventRequest(@RequestParam("sender") String sender, @RequestParam("receiver") String receiver) { - logger.info("sending from {} to {}", sender, receiver); - - // ...sending process... - - EventData data = new EventData(); - data.setEventDateTime(new Date()); - data.setEventType("sending"); - String confirm = UUID.randomUUID() - .toString(); - data.setEventId(confirm); - data.put("from", sender); - data.put("to", receiver); - EventLogger.logEvent(data); - - return "finished"; - } - - @GetMapping("/slf4j-guide-locale-request") - public String clientLocaleRequest(@RequestHeader("Accept-Language") String localeHeader) { - List list = Locale.LanguageRange.parse(localeHeader); - Locale locale = Locale.lookup(list, Arrays.asList(Locale.getAvailableLocales())); - IMessageConveyor messageConveyor = new MessageConveyor(locale); - LocLoggerFactory llFactory = new LocLoggerFactory(messageConveyor); - LocLogger locLogger = llFactory.getLocLogger(this.getClass()); - locLogger.info(Messages.CLIENT_REQUEST, "parametrizedClientId", localeHeader); - locLogger.debug(Messages.REQUEST_STARTED); - locLogger.info(Messages.REQUEST_FINISHED); - return "finished"; - } - -} diff --git a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/l10n/Messages.java b/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/l10n/Messages.java deleted file mode 100644 index e4aacaf3be..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/l10n/Messages.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.stackify.slf4j.guide.l10n; - -import ch.qos.cal10n.BaseName; -import ch.qos.cal10n.Locale; -import ch.qos.cal10n.LocaleData; - -@BaseName("messages") -@LocaleData({ @Locale("en_US"), @Locale("es_ES") }) -public enum Messages { - CLIENT_REQUEST, REQUEST_STARTED, REQUEST_FINISHED -} diff --git a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/xlogger/XLoggerController.java b/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/xlogger/XLoggerController.java deleted file mode 100644 index 8690c0ebc9..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/xlogger/XLoggerController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stackify.slf4j.guide.xlogger; - -import org.slf4j.ext.XLogger; -import org.slf4j.ext.XLoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class XLoggerController { - - private XLogger logger = XLoggerFactory.getXLogger(XLoggerController.class); - - @GetMapping("/slf4j-guide-xlogger-request") - public Integer clientXLoggerRequest(@RequestParam("queryParam") Integer queryParam) { - logger.info("Starting process"); - logger.entry(queryParam); - Integer rest = 0; - try { - rest = queryParam % 3; - } catch (RuntimeException anyException) { - logger.catching(anyException); - } - logger.exit(rest); - return rest; - } - -} diff --git a/guest/slf4j/guide/slf4j-logback/src/main/resources/application.properties b/guest/slf4j/guide/slf4j-logback/src/main/resources/application.properties deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/guest/slf4j/guide/slf4j-logback/src/main/resources/logback-spring.xml b/guest/slf4j/guide/slf4j-logback/src/main/resources/logback-spring.xml deleted file mode 100644 index 112e79c340..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - %marker %d{yyyy-MM-dd HH:mm:ss.SSS} -%5p %X{clientId}@%15.15t %-40.40logger{39} : %m%n - - - - - - \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_en_US.properties b/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_en_US.properties deleted file mode 100644 index a35dd60da3..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_en_US.properties +++ /dev/null @@ -1,3 +0,0 @@ -CLIENT_REQUEST=Client {0} has made a request using locale {1} -REQUEST_STARTED=Request started -REQUEST_FINISHED=Request finished \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_es_ES.properties b/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_es_ES.properties deleted file mode 100644 index 6cdab09236..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/main/resources/messages_es_ES.properties +++ /dev/null @@ -1,3 +0,0 @@ -CLIENT_REQUEST=El cliente {0} ha realizado una solicitud usando locale {1} -REQUEST_STARTED=Solicitud iniciada -REQUEST_FINISHED=Solicitud finalizada \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java b/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java deleted file mode 100644 index b870cc9ebd..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/controllers/SimpleControllerIntegrationTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.stackify.slf4j.guide.controllers; - -import static org.powermock.api.mockito.PowerMockito.doNothing; -import static org.powermock.api.mockito.PowerMockito.spy; - -import java.util.Collections; - -import org.assertj.core.api.Condition; -import org.assertj.core.api.SoftAssertions; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.MDC; - -import com.stackify.slf4j.guide.utils.ListAppender; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(MDC.class) -public class SimpleControllerIntegrationTest { - - SimpleController controller = new SimpleController(); - - @Before - public void clearLogList() { - ListAppender.clearEventList(); - } - - @Test - public void whenSimpleRequestMade_thenAllRegularMessagesLogged() { - String output = controller.processList(Collections.emptyList()); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("Client requested process the following list: []", Level.INFO)) - .haveAtLeastOne(eventContains("Starting process", Level.DEBUG)) - .haveAtLeastOne(eventContains("Finished processing", Level.INFO)) - .haveExactly(0, eventOfLevel(Level.ERROR)); - errorCollector.assertThat(output) - .isEqualTo("done"); - errorCollector.assertAll(); - } - - @Test - public void givenClientId_whenMDCRequestMade_thenMessagesWithClientIdLogged() throws Exception { - // We avoid cleaning the context so tht we can check it afterwards - spy(MDC.class); - doNothing().when(MDC.class); - MDC.clear(); - String clientId = "id-1234"; - - String output = controller.clientMDCRequest(clientId); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .allMatch(entry -> { - return clientId.equals(entry.getMDCPropertyMap() - .get("clientId")); - }) - .haveAtLeastOne(eventContains("Client id-1234 has made a request", Level.INFO)) - .haveAtLeastOne(eventContains("Starting request", Level.INFO)) - .haveAtLeastOne(eventContains("Finished request", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - @Test - public void whenMarkerRequestMade_thenMessagesWithMarkerLogged() throws Exception { - String output = controller.clientMarkerRequest(); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("client has made a request", Level.INFO)) - .haveAtLeastOne(eventContains("Starting request", Level.INFO, "MYMARKER")) - .haveAtLeastOne(eventContains("Finished request", Level.DEBUG, "MYMARKER")) - .haveExactly(2, eventContains(null, null, "MYMARKER")); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - @Test - public void whenProfilerRequestMade_thenMessagesWithPerformanceLogged() throws Exception { - String output = controller.clientProfilerRequest(); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("client has made a request", Level.INFO)) - .haveAtLeastOne(eventContains("Profiler [MYPROFILER]", Level.DEBUG)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - @Test - public void whenEventRequestMade_thenMessagesWithEventLogged() throws Exception { - String sender = "sender"; - String receiver = "receiver"; - String output = controller.clientEventRequest(sender, receiver); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("sending from sender to receiver", Level.INFO)) - .haveAtLeastOne(eventContains("", Level.INFO)) - .haveAtLeastOne(eventContains("sender", Level.INFO)) - .haveAtLeastOne(eventContains("receiver", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - @Test - public void givenESLocale_whenLocaleRequestMade_thenMessagesWithEventLogged() throws Exception { - String locale = "es-ES"; - String output = controller.clientLocaleRequest(locale); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("El cliente parametrizedClientId ha realizado una solicitud usando locale es-ES", Level.INFO)) - .haveAtLeastOne(eventContains("Solicitud iniciada", Level.DEBUG)) - .haveAtLeastOne(eventContains("Solicitud finalizada", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - @Test - public void givenENLocale_whenLocaleRequestMade_thenMessagesWithEventLogged() throws Exception { - String locale = "en-US"; - String output = controller.clientLocaleRequest(locale); - - SoftAssertions errorCollector = new SoftAssertions(); - errorCollector.assertThat(ListAppender.getEvents()) - .haveAtLeastOne(eventContains("Client parametrizedClientId has made a request using locale en-US", Level.INFO)) - .haveAtLeastOne(eventContains("Request started", Level.DEBUG)) - .haveAtLeastOne(eventContains("Request finished", Level.INFO)); - errorCollector.assertThat(output) - .isEqualTo("finished"); - errorCollector.assertAll(); - } - - private Condition eventContains(String substring, Level level) { - return eventContains(substring, level, null); - } - - private Condition eventOfLevel(Level level) { - return eventContains(null, level, null); - } - - private Condition eventContains(String substring, Level level, String markerName) { - - return new Condition(entry -> (substring == null || (entry.getFormattedMessage() != null && entry.getFormattedMessage() - .contains(substring))) && (level == null || level.equals(entry.getLevel())) && (markerName == null || (entry.getMarker() != null - && markerName.equals(entry.getMarker() - .getName()))), - String.format("entry with message '%s', level %s and marker %s", substring, level, markerName)); - } -} diff --git a/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java b/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java deleted file mode 100644 index e6d4e47fb2..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/test/java/com/stackify/slf4j/guide/utils/ListAppender.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.stackify.slf4j.guide.utils; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; - -public class ListAppender extends AppenderBase { - - static private List events = new ArrayList<>(); - - @Override - protected void append(ILoggingEvent eventObject) { - events.add(eventObject); - } - - public static List getEvents() { - return events; - } - - public static void clearEventList() { - events.clear(); - } -} diff --git a/guest/slf4j/guide/slf4j-logback/src/test/resources/logback-test.xml b/guest/slf4j/guide/slf4j-logback/src/test/resources/logback-test.xml deleted file mode 100644 index 90168a0fea..0000000000 --- a/guest/slf4j/guide/slf4j-logback/src/test/resources/logback-test.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/guest/spring-boot-app/WebContent/META-INF/MANIFEST.MF b/guest/spring-boot-app/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index e3c07ab38a..0000000000 --- a/guest/spring-boot-app/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: diff --git a/guest/spring-boot-app/docker/Dockerfile b/guest/spring-boot-app/docker/Dockerfile deleted file mode 100644 index 211e8927a3..0000000000 --- a/guest/spring-boot-app/docker/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# Alpine Linux with OpenJDK JRE -FROM openjdk:8-jre-alpine -RUN apk add --no-cache bash - -# copy fat WAR -COPY spring-boot-app-0.0.1-SNAPSHOT.war /app.war - -# copy fat WAR -COPY logback.xml /logback.xml - -COPY run.sh /run.sh - -# runs application -#CMD ["/usr/bin/java", "-jar", "-Dspring.profiles.active=default", "-Dlogging.config=/logback.xml", "/app.war"] - -ENTRYPOINT ["/run.sh"] diff --git a/guest/spring-boot-app/docker/logback.xml b/guest/spring-boot-app/docker/logback.xml deleted file mode 100644 index 7e03ddc827..0000000000 --- a/guest/spring-boot-app/docker/logback.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - /var/log/Application/application.log - true - - %-7d{yyyy-MM-dd HH:mm:ss:SSS} %m%n - - - - - - - diff --git a/guest/spring-boot-app/docker/run.sh b/guest/spring-boot-app/docker/run.sh deleted file mode 100755 index aeecc29371..0000000000 --- a/guest/spring-boot-app/docker/run.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -java -Dspring.profiles.active=$1 -Dlogging.config=/logback.xml -jar /app.war - diff --git a/guest/spring-boot-app/pom.xml b/guest/spring-boot-app/pom.xml deleted file mode 100644 index 6f9c8e8aa9..0000000000 --- a/guest/spring-boot-app/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - 4.0.0 - spring-boot-app - spring-boot-app - 0.0.1-SNAPSHOT - spring-boot-app - war - - - org.springframework.boot - spring-boot-starter-parent - 1.5.3.RELEASE - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-jpa - - - com.h2database - h2 - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-test - - - - - - - maven-compiler-plugin - - - maven-war-plugin - - WebContent - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - com.stackify.Application - ${project.basedir}/docker - - - - - - - - - - 8.0.43 - UTF-8 - 1.8 - - - diff --git a/guest/spring-boot-app/src/main/java/com/stackify/config/PersistenceConfig.java b/guest/spring-boot-app/src/main/java/com/stackify/config/PersistenceConfig.java deleted file mode 100644 index dfbd964228..0000000000 --- a/guest/spring-boot-app/src/main/java/com/stackify/config/PersistenceConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.stackify.config; - -import javax.sql.DataSource; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; - -@Configuration -public class PersistenceConfig { - - @Bean - public DataSource dataSource() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2).addScript("mySchema.sql").addScript("myData.sql").build(); - return db; - } - -} \ No newline at end of file diff --git a/guest/spring-boot-app/src/main/java/com/stackify/controller/EmployeeController.java b/guest/spring-boot-app/src/main/java/com/stackify/controller/EmployeeController.java deleted file mode 100644 index 44ad61fcfe..0000000000 --- a/guest/spring-boot-app/src/main/java/com/stackify/controller/EmployeeController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.stackify.controller; - -import java.util.List; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.http.HttpStatus; - -import com.stackify.model.Employee; -import com.stackify.repository.EmployeeRepository; - -@RestController -public class EmployeeController { - - private EmployeeRepository employeeRepository; - - public EmployeeController(EmployeeRepository employeeRepository) { - this.employeeRepository = employeeRepository; - } - - @PostMapping("/employees") - @ResponseStatus(HttpStatus.CREATED) - public void addEmployee(@RequestBody Employee employee) { - employeeRepository.save(employee); - } - - @GetMapping("/employees") - public List getEmployees() { - return employeeRepository.findAll(); - } -} diff --git a/guest/spring-boot-app/src/main/java/com/stackify/model/Employee.java b/guest/spring-boot-app/src/main/java/com/stackify/model/Employee.java deleted file mode 100644 index 708a990166..0000000000 --- a/guest/spring-boot-app/src/main/java/com/stackify/model/Employee.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.stackify.model; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -@Entity -public class Employee { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; - - private String name; - - public Employee() { - } - - public Employee(long id, String name) { - super(); - this.id = id; - this.name = name; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/guest/spring-boot-app/src/main/java/com/stackify/repository/EmployeeRepository.java b/guest/spring-boot-app/src/main/java/com/stackify/repository/EmployeeRepository.java deleted file mode 100644 index 583fa21ab0..0000000000 --- a/guest/spring-boot-app/src/main/java/com/stackify/repository/EmployeeRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.stackify.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.stackify.model.Employee; - -public interface EmployeeRepository extends JpaRepository { - -} diff --git a/guest/spring-boot-app/src/main/resources/application.properties b/guest/spring-boot-app/src/main/resources/application.properties deleted file mode 100644 index ac81442a1c..0000000000 --- a/guest/spring-boot-app/src/main/resources/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -server.port=8081 -server.contextPath=/springbootapp -logging.level.org.springframework.web: INFO - -spring.jpa.hibernate.ddl-auto=update \ No newline at end of file diff --git a/guest/spring-boot-app/src/main/resources/myData.sql b/guest/spring-boot-app/src/main/resources/myData.sql deleted file mode 100644 index abf63b6d5b..0000000000 --- a/guest/spring-boot-app/src/main/resources/myData.sql +++ /dev/null @@ -1 +0,0 @@ -insert into employee(name) values ('ana'); \ No newline at end of file diff --git a/guest/spring-boot-app/src/main/resources/mySchema.sql b/guest/spring-boot-app/src/main/resources/mySchema.sql deleted file mode 100644 index 48ba63d69f..0000000000 --- a/guest/spring-boot-app/src/main/resources/mySchema.sql +++ /dev/null @@ -1 +0,0 @@ -create table employee(id int identity primary key, name varchar(30)); \ No newline at end of file diff --git a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java b/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java deleted file mode 100644 index 9808546e82..0000000000 --- a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.stackify.test; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -import static org.hamcrest.Matchers.*; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -import com.stackify.Application; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = Application.class) -@WebAppConfiguration -public class EmployeeControllerUnitTest { - - private static final String CONTENT_TYPE = "application/json;charset=UTF-8"; - - private MockMvc mockMvc; - - @Autowired - private WebApplicationContext webApplicationContext; - - @Before - public void setup() throws Exception { - this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); - } - - @Test - public void whenCreateGetEmployee_thenOk() throws Exception { - String employeeJson = "{\"name\":\"john\"}"; - - this.mockMvc.perform(post("/employees").contentType(CONTENT_TYPE).content(employeeJson)).andExpect(status().isCreated()); - - this.mockMvc.perform(get("/employees")).andExpect(status().isOk()).andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$", hasSize(2))).andExpect(jsonPath("$[0].name", is("ana"))).andExpect(jsonPath("$[1].name", is("john"))); - } -} diff --git a/guest/spring-mvc/README.md b/guest/spring-mvc/README.md deleted file mode 100644 index 9e5cd64a04..0000000000 --- a/guest/spring-mvc/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Building - -To build the module, use Maven's `package` goal: - -``` -mvn clean package -``` - -## Running - -To run the application, use Spring Boot's `run` goal: - -``` -mvn spring-boot:run -``` - -The application will be accessible at [http://localhost:8080/](http://localhost:8080/) diff --git a/guest/spring-mvc/pom.xml b/guest/spring-mvc/pom.xml deleted file mode 100644 index df08fa0595..0000000000 --- a/guest/spring-mvc/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - com.stackify.guest - spring-mvc - 0.0.1-SNAPSHOT - spring-mvc - jar - Spring MVC sample project - - - org.springframework.boot - spring-boot-starter-parent - 2.0.0.RELEASE - - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - - UTF-8 - UTF-8 - - - diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java deleted file mode 100644 index b1a0e86ef4..0000000000 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.stackify.guest.springmvc.model; - -public class LoginData { - - private String login; - - private String password; - - public LoginData() { - } - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java deleted file mode 100644 index 0bd8570eed..0000000000 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.stackify.guest.springmvc.web; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - -import com.stackify.guest.springmvc.model.LoginData; - -import java.util.Collections; - -@Controller -public class InternalsController { - - private static final String LOGIN = "jack"; - private static final String PASSWORD = "halloween"; - - @GetMapping("/") - public String hello() { - return "login"; - } - - @PostMapping("/login") - public ModelAndView login(LoginData loginData) { - if (LOGIN.equals(loginData.getLogin()) && PASSWORD.equals(loginData.getPassword())) { - return new ModelAndView("success", Collections.singletonMap("login", loginData.getLogin())); - } else { - return new ModelAndView("failure", Collections.singletonMap("login", loginData.getLogin())); - } - } - - @ResponseBody - @PostMapping("/message") - public MyOutputResource sendMessage(@RequestBody MyInputResource inputResource) { - return new MyOutputResource("Received: " + inputResource.getRequestMessage()); - } - -} diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java deleted file mode 100644 index cf5815840a..0000000000 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stackify.guest.springmvc.web; - -public class MyInputResource { - - private String requestMessage; - - public String getRequestMessage() { - return requestMessage; - } - - public void setRequestMessage(String requestMessage) { - this.requestMessage = requestMessage; - } -} diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java deleted file mode 100644 index 2d0e174243..0000000000 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.stackify.guest.springmvc.web; - -public class MyOutputResource { - - private String responseMessage; - - public MyOutputResource(String responseMessage) { - this.responseMessage = responseMessage; - } - - public String getResponseMessage() { - return responseMessage; - } - -} diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java deleted file mode 100644 index edb35e6ecf..0000000000 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stackify.guest.springmvc.web; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class RestfulWebServiceController { - - @GetMapping("/message") - public MyOutputResource getMessage() { - return new MyOutputResource("Hello!"); - } - -} diff --git a/guest/spring-mvc/src/main/resources/templates/failure.html b/guest/spring-mvc/src/main/resources/templates/failure.html deleted file mode 100644 index f319652ede..0000000000 --- a/guest/spring-mvc/src/main/resources/templates/failure.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Login Failure - -

- User with login not found, please try again. -

- \ No newline at end of file diff --git a/guest/spring-mvc/src/main/resources/templates/login.html b/guest/spring-mvc/src/main/resources/templates/login.html deleted file mode 100644 index d031ac8825..0000000000 --- a/guest/spring-mvc/src/main/resources/templates/login.html +++ /dev/null @@ -1,13 +0,0 @@ - - -Login Form - - -
- - - -
- - - \ No newline at end of file diff --git a/guest/spring-mvc/src/main/resources/templates/success.html b/guest/spring-mvc/src/main/resources/templates/success.html deleted file mode 100644 index 6966385f2e..0000000000 --- a/guest/spring-mvc/src/main/resources/templates/success.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Login Success - -

- Hello, ! -

- \ No newline at end of file diff --git a/guest/spring-security/README.md b/guest/spring-security/README.md deleted file mode 100644 index 9e5cd64a04..0000000000 --- a/guest/spring-security/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Building - -To build the module, use Maven's `package` goal: - -``` -mvn clean package -``` - -## Running - -To run the application, use Spring Boot's `run` goal: - -``` -mvn spring-boot:run -``` - -The application will be accessible at [http://localhost:8080/](http://localhost:8080/) diff --git a/guest/spring-security/pom.xml b/guest/spring-security/pom.xml deleted file mode 100644 index 2ac8935c3c..0000000000 --- a/guest/spring-security/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - com.stackify.guest - spring-security - 1.0-SNAPSHOT - spring-security - Spring Security Sample Project - - - org.springframework.boot - spring-boot-starter-parent - 2.0.0.RELEASE - - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - org.thymeleaf - thymeleaf-spring5 - ${thymeleaf-spring5.version} - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-jdbc - - - com.h2database - h2 - runtime - - - - - UTF-8 - UTF-8 - 3.0.8.RELEASE - - - \ No newline at end of file diff --git a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebMvcConfiguration.java b/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebMvcConfiguration.java deleted file mode 100644 index b8dfe9050d..0000000000 --- a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebMvcConfiguration.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.stackify.guest.springsecurity.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebMvcConfiguration implements WebMvcConfigurer { - - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/customLogin").setViewName("customLogin"); - registry.addViewController("/loginSuccess").setViewName("index"); - } - -} \ No newline at end of file diff --git a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebSecurityConfig.java b/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebSecurityConfig.java deleted file mode 100644 index 164808d5b3..0000000000 --- a/guest/spring-security/src/main/java/com/stackify/guest/springsecurity/config/WebSecurityConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.stackify.guest.springsecurity.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.provisioning.JdbcUserDetailsManager; - -import javax.sql.DataSource; - -@EnableWebSecurity -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - - @Bean - public UserDetailsService jdbcUserDetailsService(DataSource dataSource) { - JdbcUserDetailsManager manager = new JdbcUserDetailsManager(); - manager.setDataSource(dataSource); - return manager; - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/css/**").permitAll() - .anyRequest().authenticated() - .and().formLogin() - .loginPage("/customLogin") - .defaultSuccessUrl("/loginSuccess", true) - .permitAll(); - } - -} \ No newline at end of file diff --git a/guest/spring-security/src/main/resources/data.sql b/guest/spring-security/src/main/resources/data.sql deleted file mode 100644 index b3f7db9105..0000000000 --- a/guest/spring-security/src/main/resources/data.sql +++ /dev/null @@ -1,2 +0,0 @@ -INSERT INTO users VALUES ('jill', '$2a$04$qUlqAEEYF1YvrpJMosodoewgL6aO.qgHytl2k5L7kdXEWnJsFdxvq', TRUE); -INSERT INTO authorities VALUES ('jill', 'USERS'); diff --git a/guest/spring-security/src/main/resources/schema.sql b/guest/spring-security/src/main/resources/schema.sql deleted file mode 100644 index 3de1b9a29f..0000000000 --- a/guest/spring-security/src/main/resources/schema.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE users ( - username VARCHAR(256) PRIMARY KEY, - password VARCHAR(256), - enabled BOOLEAN -); - -CREATE TABLE authorities ( - username VARCHAR(256) REFERENCES users (username), - authority VARCHAR(256) -); diff --git a/guest/spring-security/src/main/resources/static/css/styles.css b/guest/spring-security/src/main/resources/static/css/styles.css deleted file mode 100644 index 72bcc4934f..0000000000 --- a/guest/spring-security/src/main/resources/static/css/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.bad-login { - color: red; -} \ No newline at end of file diff --git a/guest/spring-security/src/main/resources/templates/customLogin.html b/guest/spring-security/src/main/resources/templates/customLogin.html deleted file mode 100644 index c689c78514..0000000000 --- a/guest/spring-security/src/main/resources/templates/customLogin.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - -
-
- - - - -
- - - -
Log out successful.
-
- - \ No newline at end of file diff --git a/guest/spring-security/src/main/resources/templates/index.html b/guest/spring-security/src/main/resources/templates/index.html deleted file mode 100644 index 0769f9015f..0000000000 --- a/guest/spring-security/src/main/resources/templates/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - -

Hello, !

-
- - -
- \ No newline at end of file diff --git a/guest/thread-pools/pom.xml b/guest/thread-pools/pom.xml deleted file mode 100644 index 26809fccd8..0000000000 --- a/guest/thread-pools/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - com.stackify - thread-pools - 0.0.1-SNAPSHOT - thread-pools - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - \ No newline at end of file diff --git a/guest/thread-pools/src/main/java/com/stackify/models/Employee.java b/guest/thread-pools/src/main/java/com/stackify/models/Employee.java deleted file mode 100644 index 65661f38d5..0000000000 --- a/guest/thread-pools/src/main/java/com/stackify/models/Employee.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stackify.models; - -public class Employee { - private String name; - private double salary; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getSalary() { - return salary; - } - - public void setSalary(double salary) { - this.salary = salary; - } - - public Employee(String name, double salary) { - super(); - this.name = name; - this.salary = salary; - } -} diff --git a/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java b/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java deleted file mode 100644 index 824f87a625..0000000000 --- a/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.stackify.services; - -import com.stackify.models.Employee; - -public class EmployeeService { - public double calculateBonus(Employee employee) { - return 0.1 * employee.getSalary(); - } -} diff --git a/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java b/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java deleted file mode 100644 index 2dd83d9b20..0000000000 --- a/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.stackify.threadpools; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.RecursiveTask; -import java.util.stream.IntStream; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class FactorialTask extends RecursiveTask { - - private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - - private static final long serialVersionUID = 1L; - - private int start = 1; - private int n; - - private static final int THRESHOLD = 20; - - public FactorialTask(int n) { - this.n = n; - } - - public FactorialTask(int start, int n) { - logger.info("New FactorialTask Created"); - this.start = start; - this.n = n; - } - - @Override - protected BigInteger compute() { - if ((n - start) >= THRESHOLD) { - return ForkJoinTask.invokeAll(createSubtasks()) - .stream() - .map(ForkJoinTask::join) - .reduce(BigInteger.ONE, BigInteger::multiply); - } else { - return calculate(start, n); - } - } - - private Collection createSubtasks() { - List dividedTasks = new ArrayList<>(); - - int mid = (start + n) / 2; - - dividedTasks.add(new FactorialTask(start, mid)); - dividedTasks.add(new FactorialTask(mid + 1, n)); - return dividedTasks; - } - - private BigInteger calculate(int start, int n) { - logger.info("Calculate factorial from " + start + " to " + n); - return IntStream.rangeClosed(start, n) - .mapToObj(BigInteger::valueOf) - .reduce(BigInteger.ONE, BigInteger::multiply); - } - -} diff --git a/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java b/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java deleted file mode 100644 index cc9048eee7..0000000000 --- a/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.stackify.threadpools; - -import java.math.BigInteger; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.stackify.models.Employee; -import com.stackify.services.EmployeeService; - -public class ThreadsApplication { - - private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - - public static void main(String[] args) { - testExecutor(); - testExecutorService(); - testScheduledExecutorService(); - testThreadPoolExecutor(); - testForkJoinPool(); - } - - private static EmployeeService employeeService = new EmployeeService(); - - public static void testExecutor() { - Executor executor = Executors.newSingleThreadExecutor(); - executor.execute(() -> System.out.println("Single thread pool test")); - } - - public static void testExecutorService() { - - Employee employee = new Employee("John", 2000); - - ExecutorService executor = Executors.newFixedThreadPool(10); - - Callable callableTask = () -> { - return employeeService.calculateBonus(employee); - }; - Future future = executor.submit(callableTask); - - try { - if (future.isDone()) { - double result = future.get(); - System.out.println("Bonus is:" + result); - } - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - - executor.shutdown(); - } - - public static void testScheduledExecutorService() { - Employee employee = new Employee("John", 2000); - - ScheduledExecutorService executor = Executors.newScheduledThreadPool(10); - - Callable callableTask = () -> { - return employeeService.calculateBonus(employee); - }; - - Future futureScheduled = executor.schedule(callableTask, 2, TimeUnit.MILLISECONDS); - - try { - System.out.println("Bonus:" + futureScheduled.get()); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - - executor.scheduleAtFixedRate(() -> System.out.println("Fixed Rate Scheduled"), 2, 2000, TimeUnit.MILLISECONDS); - executor.scheduleWithFixedDelay(() -> System.out.println("Fixed Delay Scheduled"), 2, 2000, TimeUnit.MILLISECONDS); - } - - public static void testThreadPoolExecutor() { - ThreadPoolExecutor fixedPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10); - ThreadPoolExecutor cachedPoolExecutor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); - - ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 6, 60, TimeUnit.SECONDS, new LinkedBlockingQueue()); - executor.setMaximumPoolSize(8); - - ScheduledThreadPoolExecutor scheduledExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5); - } - - public static void testForkJoinPool() { - ForkJoinPool pool = ForkJoinPool.commonPool(); - logger.info("Thread Pool Created"); - BigInteger result = pool.invoke(new FactorialTask(100)); - System.out.println(result.toString()); - } -} diff --git a/guest/tomcat-app/WebContent/META-INF/MANIFEST.MF b/guest/tomcat-app/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index 254272e1c0..0000000000 --- a/guest/tomcat-app/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/guest/tomcat-app/WebContent/WEB-INF/web.xml b/guest/tomcat-app/WebContent/WEB-INF/web.xml deleted file mode 100644 index efc7c9ae0d..0000000000 --- a/guest/tomcat-app/WebContent/WEB-INF/web.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - tomcat-app - - tomcat-app - org.glassfish.jersey.servlet.ServletContainer - - javax.ws.rs.Application - com.stackify.ApplicationInitializer - - 1 - - - tomcat-app - /* - - - javamelody - net.bull.javamelody.MonitoringFilter - - gzip-compression-disabled - true - - - \ No newline at end of file diff --git a/guest/tomcat-app/pom.xml b/guest/tomcat-app/pom.xml deleted file mode 100644 index acdecc445c..0000000000 --- a/guest/tomcat-app/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - com.stackify - tomcat-app - 0.0.1-SNAPSHOT - tomcat-app - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - - - - org.glassfish.jersey.containers - jersey-container-servlet - ${jersey-container-servlet.version} - - - org.glassfish.jersey.media - jersey-media-moxy - ${jersey-media-moxy.version} - - - io.rest-assured - rest-assured - ${rest-assured.version} - - - com.h2 - h2 - ${h2.version} - runtime - - - org.apache.logging.log4j - log4j-core - ${log4j-core.version} - - - net.bull.javamelody - javamelody-core - ${javamelody-core.version} - - - - - - - maven-war-plugin - ${maven-war-plugin.version} - - WebContent - - - - - - - 2.25.1 - 3.0.3 - 2.8.2 - 1.69.0 - 2.25.1 - 3.0.0 - - - \ No newline at end of file diff --git a/guest/tomcat-app/src/main/java/com/stackify/ApplicationInitializer.java b/guest/tomcat-app/src/main/java/com/stackify/ApplicationInitializer.java deleted file mode 100644 index 6d864e859e..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/ApplicationInitializer.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.stackify; - -import org.glassfish.jersey.server.ResourceConfig; - -public class ApplicationInitializer extends ResourceConfig { - public ApplicationInitializer() { - packages("com.stackify.services"); - } -} diff --git a/guest/tomcat-app/src/main/java/com/stackify/daos/UserDAO.java b/guest/tomcat-app/src/main/java/com/stackify/daos/UserDAO.java deleted file mode 100644 index b57b230135..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/daos/UserDAO.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.stackify.daos; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import com.stackify.models.User; -import com.stackify.utils.ConnectionUtil; - -public class UserDAO { - - private Logger logger = LogManager.getLogger(UserDAO.class); - - public void createTable() { - try (Connection con = ConnectionUtil.getConnection()) { - String createQuery = "CREATE TABLE IF NOT EXISTS users(email varchar(50) primary key, name varchar(50))"; - PreparedStatement pstmt = con.prepareStatement(createQuery); - - pstmt.execute(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - - } - - public void add(User user) { - try (Connection con = ConnectionUtil.getConnection()) { - - String insertQuery = "INSERT INTO users(email,name) VALUES(?,?)"; - PreparedStatement pstmt = con.prepareStatement(insertQuery); - pstmt.setString(1, user.getEmail()); - pstmt.setString(2, user.getName()); - - pstmt.executeUpdate(); - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - } - - public List findAll() { - List users = new ArrayList<>(); - - try (Connection con = ConnectionUtil.getConnection()) { - String query = "SELECT * FROM users"; - PreparedStatement pstmt = con.prepareStatement(query); - - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - User user = new User(); - user.setEmail(rs.getString("email")); - user.setName(rs.getString("name")); - users.add(user); - } - } catch (SQLException exc) { - logger.error(exc.getMessage()); - } - - return users; - } - -} diff --git a/guest/tomcat-app/src/main/java/com/stackify/models/User.java b/guest/tomcat-app/src/main/java/com/stackify/models/User.java deleted file mode 100644 index 8c8073357d..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.stackify.models; - -import javax.ws.rs.core.Link; - -public class User { - private String email; - private String name; - private Link link; - - public User() { - } - - public User(String email, String name) { - super(); - this.email = email; - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Link getLink() { - return link; - } - - public void setLink(Link link) { - this.link = link; - } - -} diff --git a/guest/tomcat-app/src/main/java/com/stackify/services/CorsFilter.java b/guest/tomcat-app/src/main/java/com/stackify/services/CorsFilter.java deleted file mode 100644 index 267aa6fd61..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/services/CorsFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.stackify.services; - -import java.io.IOException; - -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.ext.Provider; - -@Provider -public class CorsFilter implements ContainerResponseFilter { - - @Override - public void filter(final ContainerRequestContext requestContext, - final ContainerResponseContext response) throws IOException { - response.getHeaders().add("Access-Control-Allow-Origin", "*"); - response.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept"); - } -} diff --git a/guest/tomcat-app/src/main/java/com/stackify/services/UserService.java b/guest/tomcat-app/src/main/java/com/stackify/services/UserService.java deleted file mode 100644 index 6cdb3eb55f..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/services/UserService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.stackify.services; - -import java.util.List; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.stackify.daos.UserDAO; -import com.stackify.models.User; - -@Path("/users") -public class UserService { - private UserDAO userDao = new UserDAO(); - - public UserService (){ - userDao.createTable(); - } - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response addUser(User user) { - userDao.add(user); - return Response.ok() - .build(); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - public List getUsers() { - return userDao.findAll(); - } -} diff --git a/guest/tomcat-app/src/main/java/com/stackify/utils/ConnectionUtil.java b/guest/tomcat-app/src/main/java/com/stackify/utils/ConnectionUtil.java deleted file mode 100644 index e7734f64a7..0000000000 --- a/guest/tomcat-app/src/main/java/com/stackify/utils/ConnectionUtil.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.stackify.utils; - -import java.sql.Connection; -import java.sql.SQLException; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.sql.DataSource; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class ConnectionUtil { - - private static Logger logger = LogManager.getLogger(ConnectionUtil.class); - - public static Connection getConnection() { - try { - String jndiName = "java:/comp/env/jdbc/MyDataSource"; - - Context initialContext = new InitialContext(); - DataSource datasource = (DataSource)initialContext.lookup(jndiName); - if (datasource != null) { - return datasource.getConnection(); - } - else { - logger.error("Failed to lookup datasource."); - } - } - - catch (NamingException | SQLException exc) { - logger.error(exc.getMessage()); - } - return null; - } - -} diff --git a/guest/webservices/rest-client/WebContent/META-INF/MANIFEST.MF b/guest/webservices/rest-client/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index 254272e1c0..0000000000 --- a/guest/webservices/rest-client/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/guest/webservices/rest-client/pom.xml b/guest/webservices/rest-client/pom.xml deleted file mode 100644 index b05e435c4c..0000000000 --- a/guest/webservices/rest-client/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - 4.0.0 - com.stackify - rest-client - 0.0.1-SNAPSHOT - rest-client - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../../ - - - - - - maven-war-plugin - ${maven-war-plugin.version} - - WebContent - false - - - - - - \ No newline at end of file diff --git a/guest/webservices/rest-client/rest-client/.angular-cli.json b/guest/webservices/rest-client/rest-client/.angular-cli.json deleted file mode 100644 index 5d1839d374..0000000000 --- a/guest/webservices/rest-client/rest-client/.angular-cli.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "project": { - "name": "rest-client" - }, - "apps": [ - { - "root": "src", - "outDir": "dist", - "assets": [ - "assets", - "favicon.ico" - ], - "index": "index.html", - "main": "main.ts", - "polyfills": "polyfills.ts", - "test": "test.ts", - "tsconfig": "tsconfig.app.json", - "testTsconfig": "tsconfig.spec.json", - "prefix": "app", - "styles": [ - "styles.css" - ], - "scripts": [], - "environmentSource": "environments/environment.ts", - "environments": { - "dev": "environments/environment.ts", - "prod": "environments/environment.prod.ts" - } - } - ], - "e2e": { - "protractor": { - "config": "./protractor.conf.js" - } - }, - "lint": [ - { - "project": "src/tsconfig.app.json" - }, - { - "project": "src/tsconfig.spec.json" - }, - { - "project": "e2e/tsconfig.e2e.json" - } - ], - "test": { - "karma": { - "config": "./karma.conf.js" - } - }, - "defaults": { - "styleExt": "css", - "component": {} - } -} diff --git a/guest/webservices/rest-client/rest-client/.editorconfig b/guest/webservices/rest-client/rest-client/.editorconfig deleted file mode 100644 index 6e87a003da..0000000000 --- a/guest/webservices/rest-client/rest-client/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# Editor configuration, see http://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/guest/webservices/rest-client/rest-client/.gitignore b/guest/webservices/rest-client/rest-client/.gitignore deleted file mode 100644 index 54bfd2001e..0000000000 --- a/guest/webservices/rest-client/rest-client/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# compiled output -/dist -/tmp -/out-tsc - -# dependencies -/node_modules - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -# misc -/.sass-cache -/connect.lock -/coverage -/libpeerconnection.log -npm-debug.log -testem.log -/typings - -# e2e -/e2e/*.js -/e2e/*.map - -# System Files -.DS_Store -Thumbs.db diff --git a/guest/webservices/rest-client/rest-client/README.md b/guest/webservices/rest-client/rest-client/README.md deleted file mode 100644 index b33d171f3c..0000000000 --- a/guest/webservices/rest-client/rest-client/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# RestClient - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.1.3. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). -Before running the tests make sure you are serving the app via `ng serve`. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/guest/webservices/rest-client/rest-client/e2e/app.e2e-spec.ts b/guest/webservices/rest-client/rest-client/e2e/app.e2e-spec.ts deleted file mode 100644 index 2eb6dade08..0000000000 --- a/guest/webservices/rest-client/rest-client/e2e/app.e2e-spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { RestClientPage } from './app.po'; - -describe('rest-client App', () => { - let page: RestClientPage; - - beforeEach(() => { - page = new RestClientPage(); - }); - - it('should display welcome message', () => { - page.navigateTo(); - expect(page.getParagraphText()).toEqual('Welcome to app!!'); - }); -}); diff --git a/guest/webservices/rest-client/rest-client/e2e/app.po.ts b/guest/webservices/rest-client/rest-client/e2e/app.po.ts deleted file mode 100644 index 1e111a7ff6..0000000000 --- a/guest/webservices/rest-client/rest-client/e2e/app.po.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { browser, by, element } from 'protractor'; - -export class RestClientPage { - navigateTo() { - return browser.get('/'); - } - - getParagraphText() { - return element(by.css('app-root h1')).getText(); - } -} diff --git a/guest/webservices/rest-client/rest-client/e2e/tsconfig.e2e.json b/guest/webservices/rest-client/rest-client/e2e/tsconfig.e2e.json deleted file mode 100644 index e2a9a2fc77..0000000000 --- a/guest/webservices/rest-client/rest-client/e2e/tsconfig.e2e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/e2e", - "module": "commonjs", - "target": "es5", - "types": [ - "jasmine", - "node" - ] - } -} diff --git a/guest/webservices/rest-client/rest-client/karma.conf.js b/guest/webservices/rest-client/rest-client/karma.conf.js deleted file mode 100644 index 4d9ab9d948..0000000000 --- a/guest/webservices/rest-client/rest-client/karma.conf.js +++ /dev/null @@ -1,33 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/0.13/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular/cli'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - require('@angular/cli/plugins/karma') - ], - client:{ - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - reports: [ 'html', 'lcovonly' ], - fixWebpackSourcePaths: true - }, - angularCli: { - environment: 'dev' - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false - }); -}; diff --git a/guest/webservices/rest-client/rest-client/package.json b/guest/webservices/rest-client/rest-client/package.json deleted file mode 100644 index b10090830c..0000000000 --- a/guest/webservices/rest-client/rest-client/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "rest-client", - "version": "0.0.0", - "license": "MIT", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "test": "ng test", - "lint": "ng lint", - "e2e": "ng e2e" - }, - "private": true, - "dependencies": { - "@angular/animations": "^4.0.0", - "@angular/common": "^4.0.0", - "@angular/compiler": "^4.0.0", - "@angular/core": "^4.0.0", - "@angular/forms": "^4.0.0", - "@angular/http": "^4.0.0", - "@angular/platform-browser": "^4.0.0", - "@angular/platform-browser-dynamic": "^4.0.0", - "@angular/router": "^4.0.0", - "core-js": "^2.4.1", - "rxjs": "^5.1.0", - "zone.js": "^0.8.4" - }, - "devDependencies": { - "@angular/cli": "1.1.3", - "@angular/compiler-cli": "^4.0.0", - "@angular/language-service": "^4.0.0", - "@types/jasmine": "2.5.45", - "@types/node": "~6.0.60", - "codelyzer": "~3.0.1", - "jasmine-core": "~2.6.2", - "jasmine-spec-reporter": "~4.1.0", - "karma": "~1.7.0", - "karma-chrome-launcher": "~2.1.1", - "karma-cli": "~1.0.1", - "karma-coverage-istanbul-reporter": "^1.2.1", - "karma-jasmine": "~1.1.0", - "karma-jasmine-html-reporter": "^0.2.2", - "protractor": "~5.1.2", - "ts-node": "~3.0.4", - "tslint": "~5.3.2", - "typescript": "~2.3.3" - } -} diff --git a/guest/webservices/rest-client/rest-client/protractor.conf.js b/guest/webservices/rest-client/rest-client/protractor.conf.js deleted file mode 100644 index 7ee3b5ee86..0000000000 --- a/guest/webservices/rest-client/rest-client/protractor.conf.js +++ /dev/null @@ -1,28 +0,0 @@ -// Protractor configuration file, see link for more information -// https://github.com/angular/protractor/blob/master/lib/config.ts - -const { SpecReporter } = require('jasmine-spec-reporter'); - -exports.config = { - allScriptsTimeout: 11000, - specs: [ - './e2e/**/*.e2e-spec.ts' - ], - capabilities: { - 'browserName': 'chrome' - }, - directConnect: true, - baseUrl: 'http://localhost:4200/', - framework: 'jasmine', - jasmineNodeOpts: { - showColors: true, - defaultTimeoutInterval: 30000, - print: function() {} - }, - onPrepare() { - require('ts-node').register({ - project: 'e2e/tsconfig.e2e.json' - }); - jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); - } -}; diff --git a/guest/webservices/rest-client/rest-client/src/app/app.component.css b/guest/webservices/rest-client/rest-client/src/app/app.component.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/guest/webservices/rest-client/rest-client/src/app/app.component.html b/guest/webservices/rest-client/rest-client/src/app/app.component.html deleted file mode 100644 index 94dc25088b..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/app.component.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Angular QuickStart - - - - - - - loading users component - - \ No newline at end of file diff --git a/guest/webservices/rest-client/rest-client/src/app/app.component.spec.ts b/guest/webservices/rest-client/rest-client/src/app/app.component.spec.ts deleted file mode 100644 index 7d2799ceb6..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/app.component.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { TestBed, async } from '@angular/core/testing'; - -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ - AppComponent - ], - }).compileComponents(); - })); - - it('should create the app', async(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app).toBeTruthy(); - })); - - it(`should have as title 'app'`, async(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('app'); - })); - - it('should render title in a h1 tag', async(() => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!'); - })); -}); diff --git a/guest/webservices/rest-client/rest-client/src/app/app.component.ts b/guest/webservices/rest-client/rest-client/src/app/app.component.ts deleted file mode 100644 index 7b0f672831..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'] -}) -export class AppComponent { - title = 'app'; -} diff --git a/guest/webservices/rest-client/rest-client/src/app/app.module.ts b/guest/webservices/rest-client/rest-client/src/app/app.module.ts deleted file mode 100644 index fe90536b1e..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/app.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; -import { HttpModule } from '@angular/http'; -import { FormsModule } from '@angular/forms'; - -import { AppComponent } from './app.component'; -import { UsersComponent } from './users.component'; -import { RouterModule } from '@angular/router'; - -@NgModule({ - declarations: [ - AppComponent, - UsersComponent - ], - imports: [ - BrowserModule, - HttpModule, - FormsModule, - RouterModule.forRoot([ - { path: '', component: AppComponent }, - { path: 'users', component: UsersComponent }])], - providers: [], - bootstrap: [AppComponent] -}) -export class AppModule { } diff --git a/guest/webservices/rest-client/rest-client/src/app/app.service.ts b/guest/webservices/rest-client/rest-client/src/app/app.service.ts deleted file mode 100644 index cf57aecbc9..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/app.service.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Injectable} from '@angular/core'; -import { Http, Response, Headers, RequestOptions } from '@angular/http'; -import 'rxjs/add/operator/map'; - -export class User { - constructor( - public email: string, - public name: string) { } -} - -@Injectable() -export class UserService { - constructor( - private _http: Http){} - - url = 'http://localhost:8080/rest-server/users'; - - addUser(user){ - let headers = new Headers({'Content-Type': 'application/json'}); - let options = new RequestOptions({ headers: headers}); - - return this._http.post(this.url, JSON.stringify(user), options) - .map( - (_response: Response) => { - return _response; - }, - err => alert('Error adding user')); - } - - getUsers() { - return this._http.get(this.url) - .map((_response: Response) => { - return _response.json(); - }); - } -} \ No newline at end of file diff --git a/guest/webservices/rest-client/rest-client/src/app/users.component.html b/guest/webservices/rest-client/rest-client/src/app/users.component.html deleted file mode 100644 index bbf9289080..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/users.component.html +++ /dev/null @@ -1,15 +0,0 @@ -
-Email:
-Name:
- -
- -
- - - - - -
{{user.email}} -{{user.name}}
- diff --git a/guest/webservices/rest-client/rest-client/src/app/users.component.ts b/guest/webservices/rest-client/rest-client/src/app/users.component.ts deleted file mode 100644 index 6c5a383848..0000000000 --- a/guest/webservices/rest-client/rest-client/src/app/users.component.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Component } from '@angular/core'; -import {UserService, User} from './app.service'; - -@Component({ - selector: 'users-page', - providers: [UserService], - templateUrl: './users.component.html', - styleUrls: ['./app.component.css'] -}) -export class UsersComponent { - title = 'Users'; - - constructor( - private _service:UserService){} - - public user = {email: "", name: ""}; - public res=[]; - - addUser() { - this._service.addUser(this.user) - .subscribe( () => this.getUsers()); - } - - getUsers() { - this._service.getUsers() - .subscribe( - users => { - this.res=[]; - users.forEach(usr => { - this.res.push( - new User( - usr.email, - usr.name - ) - ) - }); - }); - } -} diff --git a/guest/webservices/rest-client/rest-client/src/assets/.gitkeep b/guest/webservices/rest-client/rest-client/src/assets/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/guest/webservices/rest-client/rest-client/src/environments/environment.prod.ts b/guest/webservices/rest-client/rest-client/src/environments/environment.prod.ts deleted file mode 100644 index 3612073bc3..0000000000 --- a/guest/webservices/rest-client/rest-client/src/environments/environment.prod.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const environment = { - production: true -}; diff --git a/guest/webservices/rest-client/rest-client/src/environments/environment.ts b/guest/webservices/rest-client/rest-client/src/environments/environment.ts deleted file mode 100644 index b7f639aeca..0000000000 --- a/guest/webservices/rest-client/rest-client/src/environments/environment.ts +++ /dev/null @@ -1,8 +0,0 @@ -// The file contents for the current environment will overwrite these during build. -// The build system defaults to the dev environment which uses `environment.ts`, but if you do -// `ng build --env=prod` then `environment.prod.ts` will be used instead. -// The list of which env maps to which file can be found in `.angular-cli.json`. - -export const environment = { - production: false -}; diff --git a/guest/webservices/rest-client/rest-client/src/favicon.ico b/guest/webservices/rest-client/rest-client/src/favicon.ico deleted file mode 100644 index 8081c7ceaf..0000000000 Binary files a/guest/webservices/rest-client/rest-client/src/favicon.ico and /dev/null differ diff --git a/guest/webservices/rest-client/rest-client/src/index.html b/guest/webservices/rest-client/rest-client/src/index.html deleted file mode 100644 index 5714e185ca..0000000000 --- a/guest/webservices/rest-client/rest-client/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - RestClient - - - - - - - - - diff --git a/guest/webservices/rest-client/rest-client/src/main.ts b/guest/webservices/rest-client/rest-client/src/main.ts deleted file mode 100644 index a9ca1caf8c..0000000000 --- a/guest/webservices/rest-client/rest-client/src/main.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/guest/webservices/rest-client/rest-client/src/polyfills.ts b/guest/webservices/rest-client/rest-client/src/polyfills.ts deleted file mode 100644 index fd01cc9f1d..0000000000 --- a/guest/webservices/rest-client/rest-client/src/polyfills.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), - * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. - * - * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** IE9, IE10 and IE11 requires all of the following polyfills. **/ -// import 'core-js/es6/symbol'; -// import 'core-js/es6/object'; -// import 'core-js/es6/function'; -// import 'core-js/es6/parse-int'; -// import 'core-js/es6/parse-float'; -// import 'core-js/es6/number'; -// import 'core-js/es6/math'; -// import 'core-js/es6/string'; -// import 'core-js/es6/date'; -// import 'core-js/es6/array'; -// import 'core-js/es6/regexp'; -// import 'core-js/es6/map'; -// import 'core-js/es6/weak-map'; -// import 'core-js/es6/set'; - -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ -// import 'classlist.js'; // Run `npm install --save classlist.js`. - -/** IE10 and IE11 requires the following to support `@angular/animation`. */ -// import 'web-animations-js'; // Run `npm install --save web-animations-js`. - - -/** Evergreen browsers require these. **/ -import 'core-js/es6/reflect'; -import 'core-js/es7/reflect'; - - -/** ALL Firefox browsers require the following to support `@angular/animation`. **/ -// import 'web-animations-js'; // Run `npm install --save web-animations-js`. - - - -/*************************************************************************************************** - * Zone JS is required by Angular itself. - */ -import 'zone.js/dist/zone'; // Included with Angular CLI. - - - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ - -/** - * Date, currency, decimal and percent pipes. - * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 - */ -// import 'intl'; // Run `npm install --save intl`. -/** - * Need to import at least one locale-data with intl. - */ -// import 'intl/locale-data/jsonp/en'; diff --git a/guest/webservices/rest-client/rest-client/src/styles.css b/guest/webservices/rest-client/rest-client/src/styles.css deleted file mode 100644 index 90d4ee0072..0000000000 --- a/guest/webservices/rest-client/rest-client/src/styles.css +++ /dev/null @@ -1 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ diff --git a/guest/webservices/rest-client/rest-client/src/test.ts b/guest/webservices/rest-client/rest-client/src/test.ts deleted file mode 100644 index cd612eeb0e..0000000000 --- a/guest/webservices/rest-client/rest-client/src/test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy.js'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/jasmine-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. -declare const __karma__: any; -declare const require: any; - -// Prevent Karma from running prematurely. -__karma__.loaded = function () {}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() -); -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().map(context); -// Finally, start Karma to run the tests. -__karma__.start(); diff --git a/guest/webservices/rest-client/rest-client/src/tsconfig.app.json b/guest/webservices/rest-client/rest-client/src/tsconfig.app.json deleted file mode 100644 index 5e2507db58..0000000000 --- a/guest/webservices/rest-client/rest-client/src/tsconfig.app.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/app", - "module": "es2015", - "baseUrl": "", - "types": [] - }, - "exclude": [ - "test.ts", - "**/*.spec.ts" - ] -} diff --git a/guest/webservices/rest-client/rest-client/src/tsconfig.spec.json b/guest/webservices/rest-client/rest-client/src/tsconfig.spec.json deleted file mode 100644 index 510e3f1fda..0000000000 --- a/guest/webservices/rest-client/rest-client/src/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/spec", - "module": "commonjs", - "target": "es5", - "baseUrl": "", - "types": [ - "jasmine", - "node" - ] - }, - "files": [ - "test.ts" - ], - "include": [ - "**/*.spec.ts", - "**/*.d.ts" - ] -} diff --git a/guest/webservices/rest-client/rest-client/src/typings.d.ts b/guest/webservices/rest-client/rest-client/src/typings.d.ts deleted file mode 100644 index ef5c7bd620..0000000000 --- a/guest/webservices/rest-client/rest-client/src/typings.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* SystemJS module definition */ -declare var module: NodeModule; -interface NodeModule { - id: string; -} diff --git a/guest/webservices/rest-client/rest-client/tsconfig.json b/guest/webservices/rest-client/rest-client/tsconfig.json deleted file mode 100644 index a35a8ee3a4..0000000000 --- a/guest/webservices/rest-client/rest-client/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "baseUrl": "src", - "sourceMap": true, - "declaration": false, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "target": "es5", - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "es2016", - "dom" - ] - } -} diff --git a/guest/webservices/rest-client/rest-client/tslint.json b/guest/webservices/rest-client/rest-client/tslint.json deleted file mode 100644 index dd117b3871..0000000000 --- a/guest/webservices/rest-client/rest-client/tslint.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "rulesDirectory": [ - "node_modules/codelyzer" - ], - "rules": { - "arrow-return-shorthand": true, - "callable-types": true, - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "curly": true, - "eofline": true, - "forin": true, - "import-blacklist": [ - true, - "rxjs" - ], - "import-spacing": true, - "indent": [ - true, - "spaces" - ], - "interface-over-type-literal": true, - "label-position": true, - "max-line-length": [ - true, - 140 - ], - "member-access": false, - "member-ordering": [ - true, - "static-before-instance", - "variables-before-functions" - ], - "no-arg": true, - "no-bitwise": true, - "no-console": [ - true, - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-super": true, - "no-empty": false, - "no-empty-interface": true, - "no-eval": true, - "no-inferrable-types": [ - true, - "ignore-params" - ], - "no-misused-new": true, - "no-non-null-assertion": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-string-throw": true, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": true, - "no-unnecessary-initializer": true, - "no-unused-expression": true, - "no-use-before-declare": true, - "no-var-keyword": true, - "object-literal-sort-keys": false, - "one-line": [ - true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" - ], - "prefer-const": true, - "quotemark": [ - true, - "single" - ], - "radix": true, - "semicolon": [ - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "typeof-compare": true, - "unified-signatures": true, - "variable-name": false, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ], - "directive-selector": [ - true, - "attribute", - "app", - "camelCase" - ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ], - "use-input-property-decorator": true, - "use-output-property-decorator": true, - "use-host-property-decorator": true, - "no-input-rename": true, - "no-output-rename": true, - "use-life-cycle-interface": true, - "use-pipe-transform-interface": true, - "component-class-suffix": true, - "directive-class-suffix": true, - "no-access-missing-member": true, - "templates-use-public": true, - "invoke-injectable": true - } -} diff --git a/guest/webservices/rest-server/WebContent/META-INF/MANIFEST.MF b/guest/webservices/rest-server/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index 254272e1c0..0000000000 --- a/guest/webservices/rest-server/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/guest/webservices/rest-server/WebContent/WEB-INF/web.xml b/guest/webservices/rest-server/WebContent/WEB-INF/web.xml deleted file mode 100644 index 46b173c59a..0000000000 --- a/guest/webservices/rest-server/WebContent/WEB-INF/web.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - rest-server - - rest-server - org.glassfish.jersey.servlet.ServletContainer - - javax.ws.rs.Application - com.stackify.ApplicationInitializer - - 1 - - - rest-server - /* - - \ No newline at end of file diff --git a/guest/webservices/rest-server/pom.xml b/guest/webservices/rest-server/pom.xml deleted file mode 100644 index ca81979b1e..0000000000 --- a/guest/webservices/rest-server/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - com.stackify - rest-server - 0.0.1-SNAPSHOT - rest-server - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../../ - - - - - org.glassfish.jersey.containers - jersey-container-servlet - ${jersey-container-servlet.version} - - - org.glassfish.jersey.media - jersey-media-moxy - ${jersey-media-moxy.version} - - - io.rest-assured - rest-assured - ${rest-assured.version} - - - - - - - maven-war-plugin - ${maven-war-plugin.version} - - WebContent - - - - - - - 2.25.1 - 3.0.3 - 2.25.1 - - - \ No newline at end of file diff --git a/guest/webservices/rest-server/src/main/java/com/stackify/ApplicationInitializer.java b/guest/webservices/rest-server/src/main/java/com/stackify/ApplicationInitializer.java deleted file mode 100644 index 6d864e859e..0000000000 --- a/guest/webservices/rest-server/src/main/java/com/stackify/ApplicationInitializer.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.stackify; - -import org.glassfish.jersey.server.ResourceConfig; - -public class ApplicationInitializer extends ResourceConfig { - public ApplicationInitializer() { - packages("com.stackify.services"); - } -} diff --git a/guest/webservices/rest-server/src/main/java/com/stackify/models/User.java b/guest/webservices/rest-server/src/main/java/com/stackify/models/User.java deleted file mode 100644 index 8c8073357d..0000000000 --- a/guest/webservices/rest-server/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.stackify.models; - -import javax.ws.rs.core.Link; - -public class User { - private String email; - private String name; - private Link link; - - public User() { - } - - public User(String email, String name) { - super(); - this.email = email; - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Link getLink() { - return link; - } - - public void setLink(Link link) { - this.link = link; - } - -} diff --git a/guest/webservices/rest-server/src/main/java/com/stackify/services/CorsFilter.java b/guest/webservices/rest-server/src/main/java/com/stackify/services/CorsFilter.java deleted file mode 100644 index 267aa6fd61..0000000000 --- a/guest/webservices/rest-server/src/main/java/com/stackify/services/CorsFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.stackify.services; - -import java.io.IOException; - -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.ext.Provider; - -@Provider -public class CorsFilter implements ContainerResponseFilter { - - @Override - public void filter(final ContainerRequestContext requestContext, - final ContainerResponseContext response) throws IOException { - response.getHeaders().add("Access-Control-Allow-Origin", "*"); - response.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept"); - } -} diff --git a/guest/webservices/rest-server/src/main/java/com/stackify/services/UserService.java b/guest/webservices/rest-server/src/main/java/com/stackify/services/UserService.java deleted file mode 100644 index e78ed4627a..0000000000 --- a/guest/webservices/rest-server/src/main/java/com/stackify/services/UserService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.stackify.services; - -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.stackify.models.User; - -@Path("/users") -public class UserService { - private static List users = new ArrayList<>(); - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response addUser(User user) { - users.add(user); - return Response.ok() - .build(); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - public List getUsers() { - return users; - } -} diff --git a/guest/webservices/rest-server/src/test/java/com/stackify/services/UserServiceLiveTest.java b/guest/webservices/rest-server/src/test/java/com/stackify/services/UserServiceLiveTest.java deleted file mode 100644 index be3992b7f7..0000000000 --- a/guest/webservices/rest-server/src/test/java/com/stackify/services/UserServiceLiveTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.stackify.services; - -import org.junit.Test; - -import io.restassured.RestAssured; -import static io.restassured.RestAssured.*; -import static org.hamcrest.CoreMatchers.*; - -public class UserServiceLiveTest { - @Test - public void whenAddUser_thenGetUserOk() { - RestAssured.baseURI = "http://localhost:8080/rest-server"; - - //@formatter:off - - String json = "{\"email\":\"john@gmail.com\",\"name\":\"John\"}"; - given() - .contentType("application/json") - .body(json) - .when() - .post("/users") - .then() - .statusCode(200); - - when() - .get("/users") - .then() - .contentType("application/json") - .body("name", hasItem("John")) - .body("email", hasItem("john@gmail.com")); - - //@formatter:on - } -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/JAXWSClient.java b/guest/webservices/soap_client/src/main/java/com/stackify/JAXWSClient.java deleted file mode 100644 index 5542fbde20..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/JAXWSClient.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.stackify; - -import com.stackify.services.DefaultUserImplService; -import com.stackify.services.User; -import com.stackify.services.UserService; -import com.stackify.services.Users; - -public class JAXWSClient { - public static void main(String[] args) { - DefaultUserImplService service = new DefaultUserImplService(); - User user = new User(); - user.setEmail("john@gmail.com"); - user.setName("John"); - UserService port = service.getDefaultUserImplPort(); - port.addUser(user); - Users users = port.getUsers(); - System.out.println(users.getUsers().iterator().next().getName()); - } -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/DefaultUserImplService.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/DefaultUserImplService.java deleted file mode 100644 index 821b969166..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/DefaultUserImplService.java +++ /dev/null @@ -1,94 +0,0 @@ - -package com.stackify.services; - -import java.net.MalformedURLException; -import java.net.URL; -import javax.xml.namespace.QName; -import javax.xml.ws.Service; -import javax.xml.ws.WebEndpoint; -import javax.xml.ws.WebServiceClient; -import javax.xml.ws.WebServiceException; -import javax.xml.ws.WebServiceFeature; - - -/** - * This class was generated by the JAX-WS RI. - * JAX-WS RI 2.2.9-b130926.1035 - * Generated source version: 2.2 - * - */ -@WebServiceClient(name = "DefaultUserImplService", targetNamespace = "http://services.stackify.com/", wsdlLocation = "http://localhost:8080/users?wsdl") -public class DefaultUserImplService - extends Service -{ - - private final static URL DEFAULTUSERIMPLSERVICE_WSDL_LOCATION; - private final static WebServiceException DEFAULTUSERIMPLSERVICE_EXCEPTION; - private final static QName DEFAULTUSERIMPLSERVICE_QNAME = new QName("http://services.stackify.com/", "DefaultUserImplService"); - - static { - URL url = null; - WebServiceException e = null; - try { - url = new URL("http://localhost:8080/users?wsdl"); - } catch (MalformedURLException ex) { - e = new WebServiceException(ex); - } - DEFAULTUSERIMPLSERVICE_WSDL_LOCATION = url; - DEFAULTUSERIMPLSERVICE_EXCEPTION = e; - } - - public DefaultUserImplService() { - super(__getWsdlLocation(), DEFAULTUSERIMPLSERVICE_QNAME); - } - - public DefaultUserImplService(WebServiceFeature... features) { - super(__getWsdlLocation(), DEFAULTUSERIMPLSERVICE_QNAME, features); - } - - public DefaultUserImplService(URL wsdlLocation) { - super(wsdlLocation, DEFAULTUSERIMPLSERVICE_QNAME); - } - - public DefaultUserImplService(URL wsdlLocation, WebServiceFeature... features) { - super(wsdlLocation, DEFAULTUSERIMPLSERVICE_QNAME, features); - } - - public DefaultUserImplService(URL wsdlLocation, QName serviceName) { - super(wsdlLocation, serviceName); - } - - public DefaultUserImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) { - super(wsdlLocation, serviceName, features); - } - - /** - * - * @return - * returns UserService - */ - @WebEndpoint(name = "DefaultUserImplPort") - public UserService getDefaultUserImplPort() { - return super.getPort(new QName("http://services.stackify.com/", "DefaultUserImplPort"), UserService.class); - } - - /** - * - * @param features - * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. - * @return - * returns UserService - */ - @WebEndpoint(name = "DefaultUserImplPort") - public UserService getDefaultUserImplPort(WebServiceFeature... features) { - return super.getPort(new QName("http://services.stackify.com/", "DefaultUserImplPort"), UserService.class, features); - } - - private static URL __getWsdlLocation() { - if (DEFAULTUSERIMPLSERVICE_EXCEPTION!= null) { - throw DEFAULTUSERIMPLSERVICE_EXCEPTION; - } - return DEFAULTUSERIMPLSERVICE_WSDL_LOCATION; - } - -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/ObjectFactory.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/ObjectFactory.java deleted file mode 100644 index d992521d9f..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/ObjectFactory.java +++ /dev/null @@ -1,48 +0,0 @@ - -package com.stackify.services; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the com.stackify.services package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.stackify.services - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link User } - * - */ - public User createUser() { - return new User(); - } - - /** - * Create an instance of {@link Users } - * - */ - public Users createUsers() { - return new Users(); - } - -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/User.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/User.java deleted file mode 100644 index d9d517f83d..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/User.java +++ /dev/null @@ -1,87 +0,0 @@ - -package com.stackify.services; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for user complex type. - * - *

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

- * <complexType name="user">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="email" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "user", propOrder = { - "email", - "name" -}) -public class User { - - protected String email; - protected String name; - - /** - * Gets the value of the email property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getEmail() { - return email; - } - - /** - * Sets the value of the email property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setEmail(String value) { - this.email = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/UserService.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/UserService.java deleted file mode 100644 index 87ab1f2f75..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/UserService.java +++ /dev/null @@ -1,47 +0,0 @@ - -package com.stackify.services; - -import javax.jws.WebMethod; -import javax.jws.WebParam; -import javax.jws.WebResult; -import javax.jws.WebService; -import javax.jws.soap.SOAPBinding; -import javax.xml.bind.annotation.XmlSeeAlso; -import javax.xml.ws.Action; - - -/** - * This class was generated by the JAX-WS RI. - * JAX-WS RI 2.2.9-b130926.1035 - * Generated source version: 2.2 - * - */ -@WebService(name = "UserService", targetNamespace = "http://services.stackify.com/") -@SOAPBinding(style = SOAPBinding.Style.RPC) -@XmlSeeAlso({ - ObjectFactory.class -}) -public interface UserService { - - - /** - * - * @param arg0 - */ - @WebMethod - @Action(input = "http://services.stackify.com/UserService/addUserRequest", output = "http://services.stackify.com/UserService/addUserResponse") - public void addUser( - @WebParam(name = "arg0", partName = "arg0") - User arg0); - - /** - * - * @return - * returns com.stackify.services.Users - */ - @WebMethod - @WebResult(partName = "return") - @Action(input = "http://services.stackify.com/UserService/getUsersRequest", output = "http://services.stackify.com/UserService/getUsersResponse") - public Users getUsers(); - -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/Users.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/Users.java deleted file mode 100644 index bde0e47b11..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/Users.java +++ /dev/null @@ -1,69 +0,0 @@ - -package com.stackify.services; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for users complex type. - * - *

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

- * <complexType name="users">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="users" type="{http://services.stackify.com/}user" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "users", propOrder = { - "users" -}) -public class Users { - - @XmlElement(nillable = true) - protected List users; - - /** - * Gets the value of the users property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the users property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getUsers().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link User } - * - * - */ - public List getUsers() { - if (users == null) { - users = new ArrayList(); - } - return this.users; - } - -} diff --git a/guest/webservices/soap_client/src/main/java/com/stackify/services/package-info.java b/guest/webservices/soap_client/src/main/java/com/stackify/services/package-info.java deleted file mode 100644 index af6d2bc25e..0000000000 --- a/guest/webservices/soap_client/src/main/java/com/stackify/services/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://services.stackify.com/") -package com.stackify.services; diff --git a/guest/webservices/soap_example/src/main/java/com/stackify/ServicePublisher.java b/guest/webservices/soap_example/src/main/java/com/stackify/ServicePublisher.java deleted file mode 100644 index 3a10b6e285..0000000000 --- a/guest/webservices/soap_example/src/main/java/com/stackify/ServicePublisher.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.stackify; - -import javax.xml.ws.Endpoint; - -import com.stackify.services.DefaultUserImpl; - -public class ServicePublisher { - public static void main(String[] args) { - Endpoint.publish("http://localhost:8080/users", new DefaultUserImpl()); - } -} diff --git a/guest/webservices/soap_example/src/main/java/com/stackify/models/User.java b/guest/webservices/soap_example/src/main/java/com/stackify/models/User.java deleted file mode 100644 index 1a9741154d..0000000000 --- a/guest/webservices/soap_example/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.stackify.models; - -public class User { - private String email; - private String name; - - public User() { - } - - public User(String email, String name) { - super(); - this.email = email; - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/guest/webservices/soap_example/src/main/java/com/stackify/models/Users.java b/guest/webservices/soap_example/src/main/java/com/stackify/models/Users.java deleted file mode 100644 index 2323a74614..0000000000 --- a/guest/webservices/soap_example/src/main/java/com/stackify/models/Users.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.stackify.models; - -import java.util.List; - -public class Users { - List users; - - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } - -} diff --git a/guest/webservices/soap_example/src/main/java/com/stackify/services/DefaultUserImpl.java b/guest/webservices/soap_example/src/main/java/com/stackify/services/DefaultUserImpl.java deleted file mode 100644 index 87d7d646c1..0000000000 --- a/guest/webservices/soap_example/src/main/java/com/stackify/services/DefaultUserImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.stackify.services; - -import java.util.ArrayList; - -import javax.jws.WebService; - -import com.stackify.models.User; -import com.stackify.models.Users; - -@WebService(endpointInterface = "com.stackify.services.UserService") -public class DefaultUserImpl implements UserService { - - ArrayList usersList = new ArrayList<>(); - - @Override - public void addUser(User user) { - usersList.add(user); - } - - @Override - public Users getUsers() { - Users users = new Users(); - users.setUsers(usersList); - return users; - } - -} diff --git a/guest/webservices/soap_example/src/main/java/com/stackify/services/UserService.java b/guest/webservices/soap_example/src/main/java/com/stackify/services/UserService.java deleted file mode 100644 index 8c57fbd061..0000000000 --- a/guest/webservices/soap_example/src/main/java/com/stackify/services/UserService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.stackify.services; - -import javax.jws.WebMethod; -import javax.jws.WebService; -import javax.jws.soap.SOAPBinding; - -import com.stackify.models.User; -import com.stackify.models.Users; - -@WebService -@SOAPBinding(style = SOAPBinding.Style.RPC) -public interface UserService { - - @WebMethod - public void addUser(User user); - - @WebMethod - public Users getUsers(); -} diff --git a/guest/webservices/spring-rest-service/WebContent/META-INF/MANIFEST.MF b/guest/webservices/spring-rest-service/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index 254272e1c0..0000000000 --- a/guest/webservices/spring-rest-service/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/guest/webservices/spring-rest-service/pom.xml b/guest/webservices/spring-rest-service/pom.xml deleted file mode 100644 index 6243f09727..0000000000 --- a/guest/webservices/spring-rest-service/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - com.stackify - spring-rest-service - 0.0.1-SNAPSHOT - spring-rest-service - war - - - org.springframework.boot - spring-boot-starter-parent - 1.5.4.RELEASE - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-hateoas - - - io.springfox - springfox-swagger2 - ${springfox-swagger2.version} - - - io.springfox - springfox-swagger-ui - ${springfox-swagger-ui.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - UTF-8 - UTF-8 - 1.8 - 2.7.0 - 2.7.0 - - - \ No newline at end of file diff --git a/guest/webservices/spring-rest-service/src/main/java/com/stackify/config/SwaggerConfig.java b/guest/webservices/spring-rest-service/src/main/java/com/stackify/config/SwaggerConfig.java deleted file mode 100644 index 0e9567b452..0000000000 --- a/guest/webservices/spring-rest-service/src/main/java/com/stackify/config/SwaggerConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.stackify.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@Configuration -@EnableSwagger2 -public class SwaggerConfig { - @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2).select() - .apis(RequestHandlerSelectors.basePackage("com.stackify.controllers")) - .paths(PathSelectors.any()) - .build(); - } -} diff --git a/guest/webservices/spring-rest-service/src/main/java/com/stackify/controllers/UserController.java b/guest/webservices/spring-rest-service/src/main/java/com/stackify/controllers/UserController.java deleted file mode 100644 index 361dbde38d..0000000000 --- a/guest/webservices/spring-rest-service/src/main/java/com/stackify/controllers/UserController.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.stackify.controllers; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.hateoas.Link; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.stackify.models.User; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; - -@RestController -public class UserController { - - private static List users = new ArrayList<>(); - - @PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE) - @ResponseStatus(HttpStatus.CREATED) - public void addUser(@RequestBody User user) { - users.add(user); - } - - @GetMapping("/users") - public List getUsers() { - users.forEach(user -> { - Link selfLink = linkTo(methodOn(UserController.class).getUsers()).slash(user.getEmail()) - .withSelfRel(); - user.getLinks().clear(); - user.add(selfLink); - }); - return users; - } - - @GetMapping("/users/{email}") - public User getUser(@PathVariable String email) { - User us = users.stream() - .filter(user -> !user.getEmail() - .equals(email)) - .findAny() - .orElse(null); - return us; - } - -} diff --git a/guest/webservices/spring-rest-service/src/main/java/com/stackify/models/User.java b/guest/webservices/spring-rest-service/src/main/java/com/stackify/models/User.java deleted file mode 100644 index b52e7f0f87..0000000000 --- a/guest/webservices/spring-rest-service/src/main/java/com/stackify/models/User.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.stackify.models; - -import org.springframework.hateoas.ResourceSupport; - -public class User extends ResourceSupport { - private String email; - private String name; - - public User() { - } - - public User(String email, String name) { - super(); - this.email = email; - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml index 84b41cdd6c..49e47afe92 100644 --- a/httpclient-simple/pom.xml +++ b/httpclient-simple/pom.xml @@ -277,7 +277,6 @@ - 19.0 1.10 4.1.4 diff --git a/immutables/pom.xml b/immutables/pom.xml index 648166fd74..7704cddbb6 100644 --- a/immutables/pom.xml +++ b/immutables/pom.xml @@ -18,12 +18,6 @@ value ${immutables.version} - - org.assertj - assertj-core - ${assertj.version} - test - org.mutabilitydetector MutabilityDetector @@ -34,7 +28,6 @@ 2.5.6 - 3.6.1 0.9.6 diff --git a/intelliJ/intelliJ-formatter.xml b/intelliJ/intelliJ-formatter.xml deleted file mode 100644 index 6e4c927da8..0000000000 --- a/intelliJ/intelliJ-formatter.xml +++ /dev/null @@ -1,39 +0,0 @@ - - \ No newline at end of file diff --git a/jackson-modules/jackson-annotations/pom.xml b/jackson-modules/jackson-annotations/pom.xml index bdc131c867..56fd6cf2fa 100644 --- a/jackson-modules/jackson-annotations/pom.xml +++ b/jackson-modules/jackson-annotations/pom.xml @@ -25,12 +25,6 @@ ${rest-assured.version} test - - org.assertj - assertj-core - ${assertj.version} - test - @@ -44,7 +38,6 @@ - 3.11.0 3.1.1 diff --git a/jackson-modules/jackson-conversions-2/README.md b/jackson-modules/jackson-conversions-2/README.md index 9986fe75b5..fa3568652a 100644 --- a/jackson-modules/jackson-conversions-2/README.md +++ b/jackson-modules/jackson-conversions-2/README.md @@ -10,4 +10,6 @@ This module contains articles about Jackson conversions. - [How to Process YAML with Jackson](https://www.baeldung.com/jackson-yaml) - [Jackson Streaming API](https://www.baeldung.com/jackson-streaming-api) - [Jackson: java.util.LinkedHashMap cannot be cast to X](https://www.baeldung.com/jackson-linkedhashmap-cannot-be-cast) +- [Deserialize Snake Case to Camel Case With Jackson](https://www.baeldung.com/jackson-deserialize-snake-to-camel-case) +- [Serialize and Deserialize Booleans as Integers With Jackson](https://www.baeldung.com/jackson-booleans-as-integers) - More articles: [[<-- prev]](../jackson-conversions) diff --git a/jackson-modules/jackson-conversions-2/pom.xml b/jackson-modules/jackson-conversions-2/pom.xml index a498c8b4f8..7e994fb52b 100644 --- a/jackson-modules/jackson-conversions-2/pom.xml +++ b/jackson-modules/jackson-conversions-2/pom.xml @@ -32,12 +32,6 @@ jackson-dataformat-csv ${jackson.version} - - org.assertj - assertj-core - ${assertj.version} - test - @@ -50,8 +44,4 @@ - - 3.11.0 - - \ No newline at end of file diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/Game.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/Game.java new file mode 100644 index 0000000000..0ad77640d4 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/Game.java @@ -0,0 +1,49 @@ +package com.baeldung.jackson.booleanAsInt; + +public class Game { + + private Long id; + private String name; + private Boolean paused; + private Boolean over; + + public Game() { + } + + public Game(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean isPaused() { + return paused; + } + + public void setPaused(Boolean paused) { + this.paused = paused; + } + + public Boolean isOver() { + return over; + } + + public void setOver(Boolean over) { + this.over = over; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonFormat.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonFormat.java new file mode 100644 index 0000000000..b97625fa6b --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonFormat.java @@ -0,0 +1,56 @@ +package com.baeldung.jackson.booleanAsInt; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; + +public class GameAnnotatedByJsonFormat { + + private Long id; + private String name; + + @JsonFormat(shape = Shape.NUMBER) + private boolean paused; + + @JsonFormat(shape = Shape.NUMBER) + private boolean over; + + public GameAnnotatedByJsonFormat() { + } + + public GameAnnotatedByJsonFormat(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isPaused() { + return paused; + } + + public void setPaused(boolean paused) { + this.paused = paused; + } + + public boolean isOver() { + return over; + } + + public void setOver(boolean over) { + this.over = over; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonSerializeDeserialize.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonSerializeDeserialize.java new file mode 100644 index 0000000000..50c6d96009 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/GameAnnotatedByJsonSerializeDeserialize.java @@ -0,0 +1,58 @@ +package com.baeldung.jackson.booleanAsInt; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class GameAnnotatedByJsonSerializeDeserialize { + + private Long id; + private String name; + + @JsonSerialize(using = NumericBooleanSerializer.class) + @JsonDeserialize(using = NumericBooleanDeserializer.class) + private Boolean paused; + + @JsonSerialize(using = NumericBooleanSerializer.class) + @JsonDeserialize(using = NumericBooleanDeserializer.class) + private Boolean over; + + public GameAnnotatedByJsonSerializeDeserialize() { + } + + public GameAnnotatedByJsonSerializeDeserialize(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean isPaused() { + return paused; + } + + public void setPaused(Boolean paused) { + this.paused = paused; + } + + public Boolean isOver() { + return over; + } + + public void setOver(Boolean over) { + this.over = over; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanDeserializer.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanDeserializer.java new file mode 100644 index 0000000000..e9cb41e91d --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanDeserializer.java @@ -0,0 +1,23 @@ +package com.baeldung.jackson.booleanAsInt; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; + +public class NumericBooleanDeserializer extends JsonDeserializer { + + @Override + public Boolean deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException { + if ("1".equals(p.getText())) { + return Boolean.TRUE; + } + if ("0".equals(p.getText())) { + return Boolean.FALSE; + } + // for other than "1" or "0" throw exception by using Jackson internals + throw ctxt.weirdStringException(p.getText(), Boolean.class, "only \"1\" or \"0\" recognized"); + } + +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanSerializer.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanSerializer.java new file mode 100644 index 0000000000..e9f7112b53 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/booleanAsInt/NumericBooleanSerializer.java @@ -0,0 +1,15 @@ +package com.baeldung.jackson.booleanAsInt; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; + +public class NumericBooleanSerializer extends JsonSerializer { + + @Override + public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + gen.writeString(value ? "1" : "0"); + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/User.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/User.java new file mode 100644 index 0000000000..17bf6f898b --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/User.java @@ -0,0 +1,22 @@ +package com.baeldung.jackson.snakecase; + +public class User { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithPropertyNames.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithPropertyNames.java new file mode 100644 index 0000000000..f9f36243ad --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithPropertyNames.java @@ -0,0 +1,26 @@ +package com.baeldung.jackson.snakecase; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UserWithPropertyNames { + @JsonProperty("first_name") + private String firstName; + @JsonProperty("last_name") + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithSnakeStrategy.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithSnakeStrategy.java new file mode 100644 index 0000000000..ffec940ed8 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/snakecase/UserWithSnakeStrategy.java @@ -0,0 +1,26 @@ +package com.baeldung.jackson.snakecase; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class UserWithSnakeStrategy { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/booleanAsInt/BooleanAsIntegerUnitTest.java b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/booleanAsInt/BooleanAsIntegerUnitTest.java new file mode 100644 index 0000000000..976f3f4915 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/booleanAsInt/BooleanAsIntegerUnitTest.java @@ -0,0 +1,132 @@ +package com.baeldung.jackson.booleanAsInt; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class BooleanAsIntegerUnitTest { + + private ObjectMapper mapper; + + @BeforeEach + public void setup() { + mapper = new ObjectMapper(); + } + + @Test + public void givenBoolean_serializedAsInteger() throws Exception { + GameAnnotatedByJsonFormat + game = new GameAnnotatedByJsonFormat(1L, "My Game"); + game.setPaused(true); + game.setOver(false); + String json = mapper.writeValueAsString(game); + + assertThat(json) + .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}"); + } + + @Test + public void givenInteger_deserializedAsBooleanByDefault() throws Exception { + // Integer "1" and "0" values deserialized correctly out of the box. + // No configuration or @JsonFormat annotation needed. + String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}"; + Game game = mapper.readValue(json, Game.class); + + assertThat(game.isPaused()).isEqualTo(true); + assertThat(game.isOver()).isEqualTo(false); + } + + @Test + public void givenBoolean_serializedAsIntegerGlobally() throws Exception { + // global configuration override for the type Boolean + mapper.configOverride(Boolean.class) + .setFormat(JsonFormat.Value.forShape(Shape.NUMBER)); + + Game game = new Game(1L, "My Game"); + game.setPaused(true); + game.setOver(false); + String json = mapper.writeValueAsString(game); + + assertThat(json) + .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}"); + } + + @Test + public void givenBooleanWithCustomSerializer_serializedAsNumericString() throws Exception { + GameAnnotatedByJsonSerializeDeserialize + game = new GameAnnotatedByJsonSerializeDeserialize(1L, "My Game"); + game.setPaused(true); + game.setOver(false); + String json = mapper.writeValueAsString(game); + + assertThat(json) + .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}"); + } + + @Test + public void givenNumericStringWithCustomDeserializer_deserializedAsBoolean() throws Exception { + String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}"; + GameAnnotatedByJsonSerializeDeserialize + game = mapper.readValue(json, GameAnnotatedByJsonSerializeDeserialize.class); + + assertThat(game.isPaused()).isEqualTo(true); + assertThat(game.isOver()).isEqualTo(false); + } + + @Test + public void givenBooleanWithCustomSerializer_serializedAsNumericStringGlobally() throws Exception { + // setting serializers globally + SimpleModule module = new SimpleModule(); + module.addSerializer(Boolean.class, new NumericBooleanSerializer()); + mapper.registerModule(module); + + Game game = new Game(1L, "My Game"); + game.setPaused(true); + game.setOver(false); + String json = mapper.writeValueAsString(game); + + assertThat(json) + .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}"); + } + + @Test + public void givenNumericStringWithCustomDeserializer_deserializedAsBooleanGlobally() throws Exception { + // setting deserializers globally + SimpleModule module = new SimpleModule(); + module.addDeserializer(Boolean.class, new NumericBooleanDeserializer()); + mapper.registerModule(module); + + String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}"; + Game game = mapper.readValue(json, Game.class); + + assertThat(game.isPaused()).isEqualTo(true); + assertThat(game.isOver()).isEqualTo(false); + } + + @Test + public void givenInvalidStringWithCustomDeserializer_throwsInvalidFormatException() { + // another number other than "1" or "0" + String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"5\"}"; + InvalidFormatException e = Assertions.assertThrows( + InvalidFormatException.class, () -> mapper.readValue(json, GameAnnotatedByJsonSerializeDeserialize.class) + ); + + assertThat(e.getValue()).isEqualTo("5"); + + // non-numeric string + String json2 = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"xxx\"}"; + InvalidFormatException e2 = Assertions.assertThrows( + InvalidFormatException.class, () -> mapper.readValue(json2, GameAnnotatedByJsonSerializeDeserialize.class) + ); + + assertThat(e2.getValue()).isEqualTo("xxx"); + } + +} diff --git a/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/snakecase/SnakeCaseUnitTest.java b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/snakecase/SnakeCaseUnitTest.java new file mode 100644 index 0000000000..c72908ccce --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/snakecase/SnakeCaseUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.jackson.snakecase; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SnakeCaseUnitTest { + + private static final String JSON = "{\"first_name\": \"Jackie\", \"last_name\": \"Chan\"}"; + + @Test(expected = UnrecognizedPropertyException.class) + public void whenExceptionThrown_thenExpectationSatisfied() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.readValue(JSON, User.class); + } + + @Test + public void givenSnakeCaseJson_whenParseWithJsonPropertyAnnotation_thenGetExpectedObject() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + UserWithPropertyNames user = objectMapper.readValue(JSON, UserWithPropertyNames.class); + assertEquals("Jackie", user.getFirstName()); + assertEquals("Chan", user.getLastName()); + } + + @Test + public void givenSnakeCaseJson_whenParseWithJsonNamingAnnotation_thenGetExpectedObject() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + UserWithSnakeStrategy user = objectMapper.readValue(JSON, UserWithSnakeStrategy.class); + assertEquals("Jackie", user.getFirstName()); + assertEquals("Chan", user.getLastName()); + } + + @Test + public void givenSnakeCaseJson_whenParseWithCustomMapper_thenGetExpectedObject() throws Exception { + ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); + User user = objectMapper.readValue(JSON, User.class); + assertEquals("Jackie", user.getFirstName()); + assertEquals("Chan", user.getLastName()); + } + +} diff --git a/jackson-modules/jackson/README.md b/jackson-modules/jackson/README.md index 50e13a5b75..0aa3dc5aef 100644 --- a/jackson-modules/jackson/README.md +++ b/jackson-modules/jackson/README.md @@ -6,9 +6,11 @@ This module contains articles about Jackson. The "REST With Spring" Classes: http://bit.ly/restwithspring -### Relevant Articles: +### Relevant Articles: + - [Using Optional with Jackson](https://www.baeldung.com/jackson-optional) - [Compare Two JSON Objects with Jackson](https://www.baeldung.com/jackson-compare-two-json-objects) - [Jackson vs Gson](https://www.baeldung.com/jackson-vs-gson) - [Inheritance with Jackson](https://www.baeldung.com/jackson-inheritance) - [Working with Tree Model Nodes in Jackson](https://www.baeldung.com/jackson-json-node-tree-model) +- [Get all the Keys in a JSON String Using JsonNode](https://www.baeldung.com/java-jsonnode-get-keys) diff --git a/jackson-modules/jackson/pom.xml b/jackson-modules/jackson/pom.xml index a4aecfa3de..9df0f40874 100644 --- a/jackson-modules/jackson/pom.xml +++ b/jackson-modules/jackson/pom.xml @@ -48,12 +48,6 @@ ${rest-assured.version} test - - org.assertj - assertj-core - ${assertj.version} - test - @@ -69,7 +63,6 @@ 3.1.1 - 3.11.0 \ No newline at end of file diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java b/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java new file mode 100644 index 0000000000..bb8e9a8646 --- /dev/null +++ b/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java @@ -0,0 +1,135 @@ +package com.baeldung.jackson.jsonnode; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; + +public class GetAllKeysFromJSON { + + public List getKeysInJsonUsingMaps(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException { + List keys = new ArrayList<>(); + Map jsonElements = mapper.readValue(json, new TypeReference>() { + }); + getAllKeys(jsonElements, keys); + return keys; + } + + private void getAllKeys(Map jsonElements, List keys) { + + jsonElements.entrySet() + .forEach(entry -> { + keys.add(entry.getKey()); + if (entry.getValue() instanceof Map) { + Map map = (Map) entry.getValue(); + getAllKeys(map, keys); + } else if (entry.getValue() instanceof List) { + List list = (List) entry.getValue(); + list.forEach(listEntry -> { + if (listEntry instanceof Map) { + Map map = (Map) listEntry; + getAllKeys(map, keys); + } + }); + } + }); + } + + public List getKeysInJsonUsingJsonNodeFieldNames(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException { + + List keys = new ArrayList<>(); + JsonNode jsonNode = mapper.readTree(json); + Iterator iterator = jsonNode.fieldNames(); + iterator.forEachRemaining(e -> keys.add(e)); + return keys; + } + + public List getAllKeysInJsonUsingJsonNodeFieldNames(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException { + + List keys = new ArrayList<>(); + JsonNode jsonNode = mapper.readTree(json); + getAllKeysUsingJsonNodeFieldNames(jsonNode, keys); + return keys; + } + + public List getAllKeysInJsonUsingJsonNodeFields(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException { + + List keys = new ArrayList<>(); + JsonNode jsonNode = mapper.readTree(json); + getAllKeysUsingJsonNodeFields(jsonNode, keys); + return keys; + } + + private void getAllKeysUsingJsonNodeFields(JsonNode jsonNode, List keys) { + + if (jsonNode.isObject()) { + Iterator> fields = jsonNode.fields(); + fields.forEachRemaining(field -> { + keys.add(field.getKey()); + getAllKeysUsingJsonNodeFieldNames((JsonNode) field.getValue(), keys); + }); + } else if (jsonNode.isArray()) { + ArrayNode arrayField = (ArrayNode) jsonNode; + arrayField.forEach(node -> { + getAllKeysUsingJsonNodeFieldNames(node, keys); + }); + } + + } + + private void getAllKeysUsingJsonNodeFieldNames(JsonNode jsonNode, List keys) { + + if (jsonNode.isObject()) { + Iterator fieldNames = jsonNode.fieldNames(); + fieldNames.forEachRemaining(fieldName -> { + keys.add(fieldName); + getAllKeysUsingJsonNodeFieldNames(jsonNode.get(fieldName), keys); + }); + } else if (jsonNode.isArray()) { + ArrayNode arrayField = (ArrayNode) jsonNode; + arrayField.forEach(node -> { + getAllKeysUsingJsonNodeFieldNames(node, keys); + }); + } + + } + + public List getKeysInJsonUsingJsonParser(String json, ObjectMapper mapper) throws IOException { + + List keys = new ArrayList<>(); + JsonNode jsonNode = mapper.readTree(json); + JsonParser jsonParser = jsonNode.traverse(); + while (!jsonParser.isClosed()) { + if (jsonParser.nextToken() == JsonToken.FIELD_NAME) { + keys.add((jsonParser.getCurrentName())); + } + } + return keys; + } + + public List getKeysInJsonUsingJsonParser(String json) throws JsonParseException, IOException { + + List keys = new ArrayList<>(); + JsonFactory factory = new JsonFactory(); + JsonParser jsonParser = factory.createParser(json); + while (!jsonParser.isClosed()) { + if (jsonParser.nextToken() == JsonToken.FIELD_NAME) { + keys.add((jsonParser.getCurrentName())); + } + } + return keys; + } +} diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java b/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java new file mode 100644 index 0000000000..5d0558ca63 --- /dev/null +++ b/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java @@ -0,0 +1,85 @@ +package com.baeldung.jackson.jsonnode; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class GetAllKeysFromJSONUnitTest { + + private static String json = "{\r\n" + " \"Name\":\"Craig\",\r\n" + " \"Age\":10,\r\n" + " \"BookInterests\":[\r\n" + " {\r\n" + " \"Book\":\"The Kite Runner\",\r\n" + " \"Author\":\"Khaled Hosseini\"\r\n" + " },\r\n" + + " {\r\n" + " \"Book\":\"Harry Potter\",\r\n" + " \"Author\":\"J. K. Rowling\"\r\n" + " }\r\n" + " ],\r\n" + " \"FoodInterests\":{\r\n" + " \"Breakfast\":[\r\n" + " {\r\n" + + " \"Bread\":\"Whole wheat\",\r\n" + " \"Beverage\":\"Fruit juice\"\r\n" + " },\r\n" + " {\r\n" + " \"Sandwich\":\"Vegetable Sandwich\",\r\n" + " \"Beverage\":\"Coffee\"\r\n" + + " }\r\n" + " ]\r\n" + " }\r\n" + "}"; + + private static ObjectMapper mapper = new ObjectMapper(); + private static GetAllKeysFromJSON getAllKeysFromJSONUtil = new GetAllKeysFromJSON(); + + // Top level keys : [Name, Age, BookInterests, FoodInterests] + // All keys: [Name, Age, BookInterests, Book, Author, Book, Author, FoodInterests, Breakfast, Bread, Beverage, Sandwich, Beverage] + + @Test + public void givenAJsonNode_whenUsingFieldNamesMethod_thenWeGetTopFieldNames() { + List keys; + try { + keys = getAllKeysFromJSONUtil.getKeysInJsonUsingJsonNodeFieldNames(json, mapper); + assertEquals(4, keys.size()); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + @Test + public void givenAJsonNode_whenUsingFieldNamesMethodForAllNodes_thenWeGetAllFieldNames() { + List keys; + try { + keys = getAllKeysFromJSONUtil.getAllKeysInJsonUsingJsonNodeFieldNames(json, mapper); + assertEquals(13, keys.size()); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + @Test + public void givenAJsonNode_whenUsingFieldsMethod_thenWeGetAllFieldNames() { + List keys; + try { + keys = getAllKeysFromJSONUtil.getAllKeysInJsonUsingJsonNodeFields(json, mapper); + assertEquals(13, keys.size()); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + @Test + public void givenAJsonNode_whenUsingJsonParserMethod_thenWeGetAllFieldNames() { + List keys; + try { + keys = getAllKeysFromJSONUtil.getKeysInJsonUsingJsonParser(json, mapper); + assertEquals(13, keys.size()); + + keys = getAllKeysFromJSONUtil.getKeysInJsonUsingJsonParser(json); + assertEquals(13, keys.size()); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + @Test + public void givenAJsonNode_whenUsingMaps_thenWeGetAllFieldNames() { + List keys; + try { + keys = getAllKeysFromJSONUtil.getKeysInJsonUsingMaps(json, mapper); + assertEquals(13, keys.size()); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + +} diff --git a/jackson-modules/pom.xml b/jackson-modules/pom.xml index 1bb684af0a..14e34a41bf 100644 --- a/jackson-modules/pom.xml +++ b/jackson-modules/pom.xml @@ -35,18 +35,6 @@ jackson-dataformat-xml ${jackson.version} - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - \ No newline at end of file diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml index 72e31ee5e3..f71cb1ffbf 100644 --- a/jackson-simple/pom.xml +++ b/jackson-simple/pom.xml @@ -21,25 +21,6 @@ jackson-dataformat-xml ${jackson.version} - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - @@ -52,9 +33,4 @@ - - - 3.11.0 - - \ No newline at end of file diff --git a/java-collections-conversions-2/pom.xml b/java-collections-conversions-2/pom.xml index 55dc6e30b6..9f8ef7addc 100644 --- a/java-collections-conversions-2/pom.xml +++ b/java-collections-conversions-2/pom.xml @@ -16,12 +16,6 @@ - - org.assertj - assertj-core - 3.17.2 - test - org.apache.commons commons-lang3 @@ -32,18 +26,6 @@ modelmapper ${modelmapper.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - io.vavr vavr diff --git a/java-collections-conversions/pom.xml b/java-collections-conversions/pom.xml index ae800b21c1..7f5ba38e3e 100644 --- a/java-collections-conversions/pom.xml +++ b/java-collections-conversions/pom.xml @@ -38,8 +38,4 @@ - - 4.4 - - \ No newline at end of file diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md index 87817331b5..75842c85a4 100644 --- a/java-collections-maps-3/README.md +++ b/java-collections-maps-3/README.md @@ -6,3 +6,4 @@ - [Optimizing HashMap’s Performance](https://www.baeldung.com/java-hashmap-optimize-performance) - [Update the Value Associated With a Key in a HashMap](https://www.baeldung.com/java-hashmap-update-value-by-key) - [Java Map – keySet() vs. entrySet() vs. values() Methods](https://www.baeldung.com/java-map-entries-methods) +- [Java IdentityHashMap Class and Its Use Cases](https://www.baeldung.com/java-identityhashmap) diff --git a/java-collections-maps-3/pom.xml b/java-collections-maps-3/pom.xml index 0cdf24e31b..a54061404d 100644 --- a/java-collections-maps-3/pom.xml +++ b/java-collections-maps-3/pom.xml @@ -16,18 +16,19 @@ + + + org.junit.jupiter + junit-jupiter-api + 5.8.1 + + org.springframework spring-core ${spring.version} test - - org.assertj - assertj-core - ${assertj.version} - test - org.apache.commons commons-collections4 @@ -36,8 +37,6 @@ - 4.1 - 3.6.1 5.2.5.RELEASE diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/identity/IdentityHashMapDemonstrator.java b/java-collections-maps-3/src/main/java/com/baeldung/map/identity/IdentityHashMapDemonstrator.java new file mode 100644 index 0000000000..3cbe09b93f --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/identity/IdentityHashMapDemonstrator.java @@ -0,0 +1,156 @@ +package com.baeldung.map.identity; + +import java.util.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class IdentityHashMapDemonstrator { + public static void main(String[] args) { + IdentityHashMap identityHashMap = createWithSimpleData(); + System.out.println("Map details: " + identityHashMap); + IdentityHashMap copiedMap = createFromAnotherMap(identityHashMap); + + updateWithNewValue(copiedMap); + iterateIdentityHashMap(copiedMap); + addNullKeyValue(); + demoHashMapVsIdentityMap(); + demoMutableKeys(); + + Map synchronizedMap = getSynchronizedMap(); + //Do multithreaded operations on synchronizedMap + } + + private static void addNullKeyValue() { + IdentityHashMap identityHashMap = new IdentityHashMap<>(); + identityHashMap.put(null, "Null Key Accepted"); + identityHashMap.put("Null Value Accepted", null); + assertEquals("Null Key Accepted", identityHashMap.get(null)); + assertEquals(null, identityHashMap.get("Null Value Accepted")); + } + + private static void iterateIdentityHashMap(IdentityHashMap identityHashMap) { + // Iterating using entrySet + System.out.println("Iterating values: "); + Set> entries = identityHashMap.entrySet(); + for (Map.Entry entry: entries) { + System.out.println(entry.getKey() + ": " + entry.getValue()); + } + + // Iterating using keySet + System.out.println("Iterating values using keySet: "); + for (String key: identityHashMap.keySet()) { + System.out.println(key + ": " + identityHashMap.get(key)); + } + + // Throws error if we modify while iterating + System.out.println("This iteration throws error: "); + try { + for (Map.Entry entry: entries) { + System.out.println(entry.getKey() + ": " + entry.getValue()); + identityHashMap.remove("title"); + } + } catch (ConcurrentModificationException ex) { + System.out.println("This exception will raise for sure, if we modify while iterating"); + } + } + + private static class Book { + String title; + int year; + + Book() { + // nothing to do + } + + Book(String title, int year) { + this.title = title; + this.year = year; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Book book = (Book) o; + return year == book.year && title.equals(book.title); + } + + @Override + public int hashCode() { + return Objects.hash(title, year); + } + + @Override + public String toString() { + return "Book{title='" + title + "', year=" + year + "}"; + } + } + + private static void demoMutableKeys() { + Book book1 = new Book("A Passage to India", 1924); + Book book2 = new Book("Invisible Man", 1953); + + HashMap hashMap = new HashMap<>(10); + hashMap.put(book1, "A great work of fiction"); + hashMap.put(book2, "won the US National Book Award"); + book2.year = 1952; + assertEquals(null, hashMap.get(book2)); + System.out.println("HashMap: " + hashMap); + + IdentityHashMap identityHashMap = new IdentityHashMap<>(10); + identityHashMap.put(book1, "A great work of fiction"); + identityHashMap.put(book2, "won the US National Book Award"); + book2.year = 1951; + assertEquals("won the US National Book Award", identityHashMap.get(book2)); + System.out.println("IdentityHashMap: " + identityHashMap); + } + + private static void demoHashMapVsIdentityMap() { + IdentityHashMap identityHashMap = new IdentityHashMap<>(); + identityHashMap.put("title", "Harry Potter and the Goblet of Fire"); + identityHashMap.put("author", "J. K. Rowling"); + identityHashMap.put("language", "English"); + identityHashMap.put("genre", "Fantasy"); + + HashMap hashMap = new HashMap<>(identityHashMap); + hashMap.put(new String("genre"), "Drama"); + assertEquals(4, hashMap.size()); + System.out.println("HashMap content: " + hashMap); + + identityHashMap.put(new String("genre"), "Drama"); + assertEquals(5, identityHashMap.size()); + System.out.println("IdentityHashMap content: " + identityHashMap); + } + + private static Map getSynchronizedMap() { + Map synchronizedMap = Collections.synchronizedMap(new IdentityHashMap()); + return synchronizedMap; + } + + private static IdentityHashMap createFromAnotherMap(Map otherMap) { + IdentityHashMap identityHashMap = new IdentityHashMap<>(otherMap); + return identityHashMap; + } + + private static void updateWithNewValue(IdentityHashMap identityHashMap) { + String oldTitle = identityHashMap.put("title", "Harry Potter and the Deathly Hallows"); + assertEquals("Harry Potter and the Goblet of Fire", oldTitle); + assertEquals("Harry Potter and the Deathly Hallows", identityHashMap.get("title")); + } + + public static void addValue(IdentityHashMap identityHashMap, String key, String value) { + identityHashMap.put(key, value); + } + + public static void addAllValues(IdentityHashMap identityHashMap, Map otherMap) { + identityHashMap.putAll(otherMap); + } + + public static IdentityHashMap createWithSimpleData() { + IdentityHashMap identityHashMap = new IdentityHashMap<>(); + identityHashMap.put("title", "Harry Potter and the Goblet of Fire"); + identityHashMap.put("author", "J. K. Rowling"); + identityHashMap.put("language", "English"); + identityHashMap.put("genre", "Fantasy"); + return identityHashMap; + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/invert/InvertHashMapExample.java b/java-collections-maps-3/src/main/java/com/baeldung/map/invert/InvertHashMapExample.java new file mode 100644 index 0000000000..a203fd17c4 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/invert/InvertHashMapExample.java @@ -0,0 +1,59 @@ +package com.baeldung.map.invert; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +public class InvertHashMapExample { + + public static void main(String[] args) { + + Map map = new HashMap<>(); + map.put("first", 1); + map.put("second", 2); + System.out.println(map); + + invertMapUsingForLoop(map); + invertMapUsingStreams(map); + invertMapUsingMapper(map); + + map.put("two", 2); + invertMapUsingGroupingBy(map); + } + + public static Map invertMapUsingForLoop(Map map) { + Map inversedMap = new HashMap(); + for (Entry entry : map.entrySet()) { + inversedMap.put(entry.getValue(), entry.getKey()); + } + System.out.println(inversedMap); + return inversedMap; + } + + public static Map invertMapUsingStreams(Map map) { + Map inversedMap = map.entrySet() + .stream() + .collect(Collectors.toMap(Entry::getValue, Entry::getKey)); + System.out.println(inversedMap); + return inversedMap; + } + + public static Map invertMapUsingMapper(Map sourceMap) { + Map inversedMap = sourceMap.entrySet() + .stream() + .collect(Collectors.toMap(Entry::getValue, Entry::getKey, (oldValue, newValue) -> oldValue)); + System.out.println(inversedMap); + return inversedMap; + } + + public static Map> invertMapUsingGroupingBy(Map map) { + Map> inversedMap = map.entrySet() + .stream() + .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList()))); + System.out.println(inversedMap); + return inversedMap; + } + +} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/identity/IdentityHashMapDemonstratorUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/identity/IdentityHashMapDemonstratorUnitTest.java new file mode 100644 index 0000000000..cc74ce4dd6 --- /dev/null +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/identity/IdentityHashMapDemonstratorUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.map.identity; + +import org.junit.jupiter.api.Test; + +import java.util.IdentityHashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class IdentityHashMapDemonstratorUnitTest { + + @Test + public void givenIdentityHashMap_whenNewObjectWithSameKey_thenAddsAsNewValue() { + IdentityHashMap identityHashMap = IdentityHashMapDemonstrator.createWithSimpleData(); + String newGenreKey = new String("genre"); + identityHashMap.put(newGenreKey, "Drama"); + + assertEquals(5, identityHashMap.size()); + assertEquals("Fantasy", identityHashMap.get("genre")); + assertEquals("Drama", identityHashMap.get(newGenreKey)); + } +} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/invert/InvertHashMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/invert/InvertHashMapUnitTest.java new file mode 100644 index 0000000000..6870cdef23 --- /dev/null +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/invert/InvertHashMapUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.map.invert; + +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class InvertHashMapUnitTest { + + Map sourceMap; + + @BeforeEach + void setup() { + sourceMap = new HashMap<>(); + sourceMap.put("Sunday", 0); + sourceMap.put("Monday", 1); + sourceMap.put("Tuesday", 2); + sourceMap.put("Wednesday", 3); + sourceMap.put("Thursday", 4); + sourceMap.put("Friday", 5); + sourceMap.put("Saturday", 6); + } + + @Test + void givenSourceMap_whenUsingForLoop_returnsInvertedMap() { + Map inversedMap = InvertHashMapExample.invertMapUsingForLoop(sourceMap); + + assertNotNull(inversedMap); + assertEquals(sourceMap.size(), inversedMap.size()); + assertEquals("Monday", inversedMap.get(1)); + } + + @Test + void givenSourceMap_whenUsingStreams_returnsInvertedMap() { + Map inversedMap = InvertHashMapExample.invertMapUsingStreams(sourceMap); + + assertNotNull(inversedMap); + assertEquals(sourceMap.size(), inversedMap.size()); + assertEquals("Monday", inversedMap.get(1)); + } + + @Test + void givenSourceMap_whenUsingMapper_returnsInvertedMap() { + Map inversedMap = InvertHashMapExample.invertMapUsingMapper(sourceMap); + + assertNotNull(inversedMap); + assertEquals(sourceMap.size(), inversedMap.size()); + assertEquals("Monday", inversedMap.get(1)); + } + + @Test + void givenSourceMapWithDuplicateValues_whenUsingGroupBy_returnsInvertedMap() { + sourceMap.put("MONDAY", 1); + Map> inversedMap = InvertHashMapExample.invertMapUsingGroupingBy(sourceMap); + + assertNotNull(inversedMap); + assertNotEquals(sourceMap.size(), inversedMap.size()); // duplicate keys are merged now + assertEquals(2, inversedMap.get(1).size()); + assertTrue(inversedMap.get(1).contains("Monday")); + assertTrue(inversedMap.get(1).contains("MONDAY")); + } + +} diff --git a/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp b/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp new file mode 100644 index 0000000000..37adb35333 --- /dev/null +++ b/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp @@ -0,0 +1,21 @@ +#include "com_baeldung_jni_RegisterNativesHelloWorldJNI.h" +#include + + +JNIEXPORT jstring JNICALL hello (JNIEnv* env, jobject thisObject) { + std::string hello = "Hello from registered native C++ !!"; + std::cout << hello << std::endl; + return env->NewStringUTF(hello.c_str()); +} + +static JNINativeMethod methods[] = { + {"sayHello", "()Ljava/lang/String;", (void*) &hello }, +}; + + +JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register (JNIEnv* env, jobject thsObject) { + jclass clazz = env->FindClass("com/baeldung/jni/RegisterNativesHelloWorldJNI"); + + (env)->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0])); +} + diff --git a/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.h b/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.h new file mode 100644 index 0000000000..bcca780208 --- /dev/null +++ b/java-native/src/main/cpp/com_baeldung_jni_RegisterNativesHelloWorldJNI.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_baeldung_jni_RegisterNativesHelloWorldJNI */ + +#ifndef _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI +#define _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_baeldung_jni_RegisterNativesHelloWorldJNI + * Method: sayHello + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_sayHello + (JNIEnv *, jobject); + +/* + * Class: com_baeldung_jni_RegisterNativesHelloWorldJNI + * Method: register + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/java-native/src/main/cpp/generateNativeLibMac.sh b/java-native/src/main/cpp/generateNativeLibMac.sh old mode 100644 new mode 100755 index d11dcc7c01..834a07acc8 --- a/java-native/src/main/cpp/generateNativeLibMac.sh +++ b/java-native/src/main/cpp/generateNativeLibMac.sh @@ -3,4 +3,5 @@ g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_HelloWorldJNI.cpp -o com_baeldung_jni_HelloWorldJNI.o g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleParametersJNI.cpp -o com_baeldung_jni_ExampleParametersJNI.o g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleObjectsJNI.cpp -o com_baeldung_jni_ExampleObjectsJNI.o -g++ -dynamiclib -o ../../../native/macos/libnative.dylib com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o -lc \ No newline at end of file +g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp -o com_baeldung_jni_RegisterNativesHelloWorldJNI.o +g++ -dynamiclib -o ../../../native/macos/libnative.dylib com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o com_baeldung_jni_RegisterNativesHelloWorldJNI.o -lc \ No newline at end of file diff --git a/java-native/src/main/java/com/baeldung/jni/RegisterNativesHelloWorldJNI.java b/java-native/src/main/java/com/baeldung/jni/RegisterNativesHelloWorldJNI.java new file mode 100644 index 0000000000..c5461aafef --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jni/RegisterNativesHelloWorldJNI.java @@ -0,0 +1,18 @@ +package com.baeldung.jni; + +public class RegisterNativesHelloWorldJNI { + + static { + System.loadLibrary("native"); + } + + public static void main(String[] args) { + RegisterNativesHelloWorldJNI helloWorldJNI = new RegisterNativesHelloWorldJNI(); + helloWorldJNI.register(); + helloWorldJNI.sayHello(); + } + + public native String sayHello(); + + public native void register(); +} diff --git a/java-native/src/test/java/com/baeldung/jni/registernatives/JNIRegisterNativesManualTest.java b/java-native/src/test/java/com/baeldung/jni/registernatives/JNIRegisterNativesManualTest.java new file mode 100644 index 0000000000..96e15bd822 --- /dev/null +++ b/java-native/src/test/java/com/baeldung/jni/registernatives/JNIRegisterNativesManualTest.java @@ -0,0 +1,26 @@ +package com.baeldung.jni.registernatives; + +import com.baeldung.jni.RegisterNativesHelloWorldJNI; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class JNIRegisterNativesManualTest { + @Before + public void setup() { + System.loadLibrary("native"); + } + + @Test + public void whenRegisteredNativeHelloWorld_thenOutputIsAsExpected() { + RegisterNativesHelloWorldJNI helloWorld = new RegisterNativesHelloWorldJNI(); + helloWorld.register(); + + String helloFromNative = helloWorld.sayHello(); + + assertNotNull(helloFromNative); + assertTrue(helloFromNative.equals("Hello from registered native C++ !!")); + } +} diff --git a/java-numbers-3/pom.xml b/java-numbers-3/pom.xml index e8e080c4c0..68c2ac98de 100644 --- a/java-numbers-3/pom.xml +++ b/java-numbers-3/pom.xml @@ -30,12 +30,6 @@ ${commons-lang3.version} test - - org.assertj - assertj-core - ${assertj.version} - test - @@ -51,7 +45,6 @@ 2.6.0 0.10.2 - 3.6.1 \ No newline at end of file diff --git a/java-numbers-4/pom.xml b/java-numbers-4/pom.xml index dbd6ac456a..9b2e799840 100644 --- a/java-numbers-4/pom.xml +++ b/java-numbers-4/pom.xml @@ -25,12 +25,6 @@ ${commons-lang3.version} test - - org.assertj - assertj-core - ${assertj.version} - test - @@ -45,7 +39,6 @@ 0.10.2 - 3.6.1 \ No newline at end of file diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml index 8bab655f73..c06bc48c5d 100644 --- a/java-numbers/pom.xml +++ b/java-numbers/pom.xml @@ -31,12 +31,6 @@ decimal4j ${decimal4j.version} - - org.assertj - assertj-core - ${assertj.version} - test - @@ -51,7 +45,6 @@ 1.0.3 - 3.6.1 \ No newline at end of file diff --git a/java-spi/exchange-rate-impl/src/main/java/com/baeldung/rate/impl/YahooQuoteManagerImpl.java b/java-spi/exchange-rate-impl/src/main/java/com/baeldung/rate/impl/YahooQuoteManagerImpl.java index 8cc68259be..f5c60699c7 100644 --- a/java-spi/exchange-rate-impl/src/main/java/com/baeldung/rate/impl/YahooQuoteManagerImpl.java +++ b/java-spi/exchange-rate-impl/src/main/java/com/baeldung/rate/impl/YahooQuoteManagerImpl.java @@ -24,7 +24,7 @@ public class YahooQuoteManagerImpl implements QuoteManager { StringBuilder sb = new StringBuilder(); Currency.getAvailableCurrencies().forEach(currency -> { - if (!currency.equals(currency.getCurrencyCode())) { + if (!baseCurrency.equals(currency.getCurrencyCode())) { sb.append(baseCurrency).append(currency.getCurrencyCode()).append("=X").append(","); } }); diff --git a/javafx/README.md b/javafx/README.md index 8ef06eb012..5e034adb38 100644 --- a/javafx/README.md +++ b/javafx/README.md @@ -3,6 +3,8 @@ This module contains articles about JavaFX. ### Relevant Articles: + - [Introduction to JavaFX](https://www.baeldung.com/javafx) - [Display Custom Items in JavaFX ListView](https://www.baeldung.com/javafx-listview-display-custom-items) +- [Adding EventHandler to JavaFX Button](https://www.baeldung.com/javafx-button-eventhandler) diff --git a/javafx/src/main/java/com/baeldung/button/eventhandler/ButtonEventHandlerController.java b/javafx/src/main/java/com/baeldung/button/eventhandler/ButtonEventHandlerController.java new file mode 100644 index 0000000000..8d54a366f0 --- /dev/null +++ b/javafx/src/main/java/com/baeldung/button/eventhandler/ButtonEventHandlerController.java @@ -0,0 +1,64 @@ +package com.baeldung.button.eventhandler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.Effect; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.text.Font; + +public class ButtonEventHandlerController { + + private static final Logger logger = LoggerFactory.getLogger(ButtonEventHandlerController.class); + + @FXML + private Button button; + + @FXML + private Label label; + + @FXML + private void initialize() { + button.setText("Click me"); + + handleClickEvent(); + handleHoverEffect(); + reuseRightClickEventHandler(); + } + + private void handleClickEvent() { + button.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + logger.info("OnAction {}", event); + } + }); + + button.setOnAction(event -> logger.info("OnAction {}", event)); + button.setOnAction(event -> logger.info("OnAction2 {}", event)); + } + + private void handleHoverEffect() { + Effect shadow = new DropShadow(); + button.setOnMouseEntered(e -> button.setEffect(shadow)); + button.setOnMouseExited(e -> button.setEffect(null)); + } + + private void reuseRightClickEventHandler() { + EventHandler rightClickHandler = event -> { + if (MouseButton.SECONDARY.equals(event.getButton())) { + button.setFont(new Font(button.getFont() + .getSize() + 1)); + } + }; + button.setOnMousePressed(rightClickHandler); + label.setOnMousePressed(rightClickHandler); + } +} diff --git a/javafx/src/main/java/com/baeldung/button/eventhandler/Main.java b/javafx/src/main/java/com/baeldung/button/eventhandler/Main.java new file mode 100644 index 0000000000..0c4e2eaa08 --- /dev/null +++ b/javafx/src/main/java/com/baeldung/button/eventhandler/Main.java @@ -0,0 +1,24 @@ +package com.baeldung.button.eventhandler; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; + +public class Main extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) throws Exception { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/button_event-handler.fxml")); + Pane page = loader.load(); + + primaryStage.setTitle("Button event handler"); + primaryStage.setScene(new Scene(page)); + primaryStage.show(); + } +} diff --git a/javafx/src/main/resources/button_event-handler.fxml b/javafx/src/main/resources/button_event-handler.fxml new file mode 100644 index 0000000000..2f7b1eeff6 --- /dev/null +++ b/javafx/src/main/resources/button_event-handler.fxml @@ -0,0 +1,16 @@ + + + + + +

+
+ + + + diff --git a/javax-servlets/pom.xml b/javax-servlets/pom.xml index f1677050cf..1dc58aa917 100644 --- a/javax-servlets/pom.xml +++ b/javax-servlets/pom.xml @@ -16,12 +16,6 @@ - - org.assertj - assertj-core - ${assertj.version} - test - commons-fileupload @@ -56,7 +50,6 @@ 4.5.3 2.8.2 - 3.9.1 4.0.1 diff --git a/javaxval/README.md b/javaxval/README.md index cc237e1e59..24c2cf98c5 100644 --- a/javaxval/README.md +++ b/javaxval/README.md @@ -11,3 +11,4 @@ This module contains articles about Bean Validation. - [Grouping Javax Validation Constraints](https://www.baeldung.com/javax-validation-groups) - [Validations for Enum Types](https://www.baeldung.com/javax-validations-enums) - [Guide to ParameterMessageInterpolator](https://www.baeldung.com/hibernate-parametermessageinterpolator) +- [Hibernate Validator Annotation Processor in Depth](https://www.baeldung.com/hibernate-validator-annotation-processor) diff --git a/javaxval/pom.xml b/javaxval/pom.xml index f0093e0aa4..4131ddeb97 100644 --- a/javaxval/pom.xml +++ b/javaxval/pom.xml @@ -15,7 +15,7 @@ - org.hibernate + org.hibernate.validator hibernate-validator ${hibernate-validator.version} @@ -34,19 +34,47 @@ spring-test ${org.springframework.version} - - org.assertj - assertj-core - ${assertj.version} - test - + + + 6.0.13.Final + 6.2.0.Final + 3.6.1 + 1.8 + 1.8 3.0.0 5.0.2.RELEASE - 3.11.1 - \ No newline at end of file + diff --git a/javaxval/src/main/java/com/baeldung/javaxval/hibernate/validator/ap/Message.java b/javaxval/src/main/java/com/baeldung/javaxval/hibernate/validator/ap/Message.java new file mode 100644 index 0000000000..55d6dafad7 --- /dev/null +++ b/javaxval/src/main/java/com/baeldung/javaxval/hibernate/validator/ap/Message.java @@ -0,0 +1,95 @@ +package com.baeldung.javaxval.hibernate.validator.ap; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; +import java.util.List; +import java.util.Optional; + +public class Message { + + @NotNull(message = "Content cannot be null") + private String content; + + private boolean isDelivered; + + private List<@NotBlank String> recipients; + + // uncomment in order to trigger AP annotation detection + // The annotation @Past is disallowed for this data type. + // @Past + private String createdAt; + + public String getContent() { + return content; + } + + public Message(String content, boolean isDelivered, List<@NotBlank String> recipients, String createdAt) { + this.content = content; + this.isDelivered = isDelivered; + this.recipients = recipients; + this.createdAt = createdAt; + } + + // uncomment in order to trigger AP annotation detection + // The annotation @Min is disallowed for the return type of this method. + // @Min(3) + public boolean broadcast() { + // setup a logic + // to send to recipients + return true; + } + + // uncomment in order to trigger AP annotation detection + // Void methods may not be annotated with constraint annotations. + // @NotNull + public void archive() { + // archive the message + } + + // uncomment in order to trigger AP annotation detection + // Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods. + // NOTE: add -AmethodConstraintsSupported=false to compiler args before + // @AssertTrue + public boolean delete() { + // delete the message + return false; + } + + public void setContent(String content) { + this.content = content; + } + + public boolean isDelivered() { + return isDelivered; + } + + public void setDelivered(boolean delivered) { + isDelivered = delivered; + } + + public List getRecipients() { + return recipients; + } + + public void setRecipients(List recipients) { + this.recipients = recipients; + } + + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + public String getName() { + return content; + } + + public void setName(String content) { + this.content = content; + } + + public Optional<@Past String> getCreatedAt() { + return Optional.ofNullable(createdAt); + } + +} diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java index 26cd5814ac..0a3da677ce 100644 --- a/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java +++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java @@ -1,48 +1,48 @@ - -package com.baeldung.jaxb.gen; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the com.baeldung.jaxb.gen package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.jaxb.gen - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link UserRequest } - * - */ - public UserRequest createUserRequest() { - return new UserRequest(); - } - - /** - * Create an instance of {@link UserResponse } - * - */ - public UserResponse createUserResponse() { - return new UserResponse(); - } - -} + +package com.baeldung.jaxb.gen; + +import javax.xml.bind.annotation.XmlRegistry; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.baeldung.jaxb.gen package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.jaxb.gen + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link UserRequest } + * + */ + public UserRequest createUserRequest() { + return new UserRequest(); + } + + /** + * Create an instance of {@link UserResponse } + * + */ + public UserResponse createUserResponse() { + return new UserResponse(); + } + +} diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java index 4cfbeb8d46..1c1abc61a6 100644 --- a/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java +++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java @@ -1,87 +1,87 @@ - -package com.baeldung.jaxb.gen; - -import java.io.Serializable; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for UserRequest complex type. - * - *

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

- * <complexType name="UserRequest">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
- *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "UserRequest", propOrder = { - "id", - "name" -}) -@XmlRootElement(name = "userRequest") -public class UserRequest - implements Serializable -{ - - private final static long serialVersionUID = -1L; - protected int id; - @XmlElement(required = true) - protected String name; - - /** - * Gets the value of the id property. - * - */ - public int getId() { - return id; - } - - /** - * Sets the value of the id property. - * - */ - public void setId(int value) { - this.id = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - -} + +package com.baeldung.jaxb.gen; + +import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for UserRequest complex type. + * + *

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

+ * <complexType name="UserRequest">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "UserRequest", propOrder = { + "id", + "name" +}) +@XmlRootElement(name = "userRequest") +public class UserRequest + implements Serializable +{ + + private final static long serialVersionUID = -1L; + protected int id; + @XmlElement(required = true) + protected String name; + + /** + * Gets the value of the id property. + * + */ + public int getId() { + return id; + } + + /** + * Sets the value of the id property. + * + */ + public void setId(int value) { + this.id = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + +} diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/UserResponse.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserResponse.java index d86778403a..b80405e4a9 100644 --- a/jaxb/src/main/java/com/baeldung/jaxb/gen/UserResponse.java +++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserResponse.java @@ -1,149 +1,149 @@ - -package com.baeldung.jaxb.gen; - -import java.io.Serializable; -import java.util.Calendar; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import org.w3._2001.xmlschema.Adapter1; - - -/** - *

Java class for UserResponse complex type. - * - *

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

- * <complexType name="UserResponse">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
- *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *         <element name="gender" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *         <element name="created" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "UserResponse", propOrder = { - "id", - "name", - "gender", - "created" -}) -@XmlRootElement(name = "userResponse") -public class UserResponse - implements Serializable -{ - - private final static long serialVersionUID = -1L; - protected int id; - @XmlElement(required = true) - protected String name; - @XmlElement(required = true) - protected String gender; - @XmlElement(required = true, type = String.class) - @XmlJavaTypeAdapter(Adapter1 .class) - @XmlSchemaType(name = "dateTime") - protected Calendar created; - - /** - * Gets the value of the id property. - * - */ - public int getId() { - return id; - } - - /** - * Sets the value of the id property. - * - */ - public void setId(int value) { - this.id = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the gender property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGender() { - return gender; - } - - /** - * Sets the value of the gender property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGender(String value) { - this.gender = value; - } - - /** - * Gets the value of the created property. - * - * @return - * possible object is - * {@link String } - * - */ - public Calendar getCreated() { - return created; - } - - /** - * Sets the value of the created property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setCreated(Calendar value) { - this.created = value; - } - -} + +package com.baeldung.jaxb.gen; + +import java.io.Serializable; +import java.util.Calendar; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.w3._2001.xmlschema.Adapter1; + + +/** + *

Java class for UserResponse complex type. + * + *

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

+ * <complexType name="UserResponse">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="gender" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="created" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "UserResponse", propOrder = { + "id", + "name", + "gender", + "created" +}) +@XmlRootElement(name = "userResponse") +public class UserResponse + implements Serializable +{ + + private final static long serialVersionUID = -1L; + protected int id; + @XmlElement(required = true) + protected String name; + @XmlElement(required = true) + protected String gender; + @XmlElement(required = true, type = String.class) + @XmlJavaTypeAdapter(Adapter1 .class) + @XmlSchemaType(name = "dateTime") + protected Calendar created; + + /** + * Gets the value of the id property. + * + */ + public int getId() { + return id; + } + + /** + * Sets the value of the id property. + * + */ + public void setId(int value) { + this.id = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the gender property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGender() { + return gender; + } + + /** + * Sets the value of the gender property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGender(String value) { + this.gender = value; + } + + /** + * Gets the value of the created property. + * + * @return + * possible object is + * {@link String } + * + */ + public Calendar getCreated() { + return created; + } + + /** + * Sets the value of the created property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCreated(Calendar value) { + this.created = value; + } + +} diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/package-info.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/package-info.java index 6384eab27f..639d00179c 100644 --- a/jaxb/src/main/java/com/baeldung/jaxb/gen/package-info.java +++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/package-info.java @@ -1,2 +1,2 @@ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.baeldung.com/jaxb/gen", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) -package com.baeldung.jaxb.gen; +@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.baeldung.com/jaxb/gen", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package com.baeldung.jaxb.gen; diff --git a/jaxb/src/main/java/org/w3/_2001/xmlschema/Adapter1.java b/jaxb/src/main/java/org/w3/_2001/xmlschema/Adapter1.java index b4865b5510..54b3c360dc 100644 --- a/jaxb/src/main/java/org/w3/_2001/xmlschema/Adapter1.java +++ b/jaxb/src/main/java/org/w3/_2001/xmlschema/Adapter1.java @@ -1,23 +1,23 @@ - -package org.w3._2001.xmlschema; - -import java.util.Calendar; -import javax.xml.bind.annotation.adapters.XmlAdapter; - -public class Adapter1 - extends XmlAdapter -{ - - - public Calendar unmarshal(String value) { - return (javax.xml.bind.DatatypeConverter.parseDateTime(value)); - } - - public String marshal(Calendar value) { - if (value == null) { - return null; - } - return (javax.xml.bind.DatatypeConverter.printDateTime(value)); - } - -} + +package org.w3._2001.xmlschema; + +import java.util.Calendar; +import javax.xml.bind.annotation.adapters.XmlAdapter; + +public class Adapter1 + extends XmlAdapter +{ + + + public Calendar unmarshal(String value) { + return (javax.xml.bind.DatatypeConverter.parseDateTime(value)); + } + + public String marshal(Calendar value) { + if (value == null) { + return null; + } + return (javax.xml.bind.DatatypeConverter.printDateTime(value)); + } + +} diff --git a/jbang/README.md b/jbang/README.md new file mode 100644 index 0000000000..bd8d2a151e --- /dev/null +++ b/jbang/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Guide to JBang](https://www.baeldung.com/jbang-guide) diff --git a/jbang/hello.java b/jbang/hello.java new file mode 100755 index 0000000000..4a457b153b --- /dev/null +++ b/jbang/hello.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +// //DEPS + +import static java.lang.System.*; + +public class hello { + + public static void main(String... args) { + out.println("Hello World"); + } +} diff --git a/jbang/hellocli.java b/jbang/hellocli.java new file mode 100755 index 0000000000..8722cb27b8 --- /dev/null +++ b/jbang/hellocli.java @@ -0,0 +1,27 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS info.picocli:picocli:4.5.0 + +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; + +import java.util.concurrent.Callable; + +@Command(name = "hellocli", mixinStandardHelpOptions = true, version = "hellocli 0.1", + description = "hellocli made with jbang") +class hellocli implements Callable { + + @Parameters(index = "0", description = "The greeting to print", defaultValue = "World!") + private String greeting; + + public static void main(String... args) { + int exitCode = new CommandLine(new hellocli()).execute(args); + System.exit(exitCode); + } + + @Override + public Integer call() throws Exception { // your business logic goes here... + System.out.println("Hello " + greeting); + return 0; + } +} diff --git a/jbang/index.html b/jbang/index.html new file mode 100644 index 0000000000..bd34d026a3 --- /dev/null +++ b/jbang/index.html @@ -0,0 +1,18 @@ + + + + + + + JBang meets Quarkus + + + + + Go Say Hello! +

+ Powered by: + +

+ + \ No newline at end of file diff --git a/jbang/jbang-catalog.json b/jbang/jbang-catalog.json new file mode 100644 index 0000000000..2e30f0eb4a --- /dev/null +++ b/jbang/jbang-catalog.json @@ -0,0 +1,15 @@ +{ + "catalogs": {}, + "aliases": { + "hello": { + "script-ref": "hello.java" + }, + "hellocli": { + "script-ref": "hellocli.java" + }, + "jbangquarkus": { + "script-ref": "jbangquarkus.java" + } + }, + "templates": {} +} \ No newline at end of file diff --git a/jbang/jbangquarkus.java b/jbang/jbangquarkus.java new file mode 100755 index 0000000000..9e3cb5f69a --- /dev/null +++ b/jbang/jbangquarkus.java @@ -0,0 +1,21 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +// Update the Quarkus version to what you want here or run jbang with +// `-Dquarkus.version=` to override it. +//DEPS io.quarkus:quarkus-bom:${quarkus.version:2.4.0.Final}@pom +//DEPS io.quarkus:quarkus-resteasy +//JAVAC_OPTIONS -parameters + +//FILES META-INF/resources/index.html=index.html + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/hello") +@ApplicationScoped +public class jbangquarkus { + @GET + public String sayHello() { + return "Hello from Quarkus with jbang.dev"; + } +} diff --git a/jenkins/plugins/pom.xml b/jenkins/plugins/pom.xml index 3662d59980..6873f0df38 100644 --- a/jenkins/plugins/pom.xml +++ b/jenkins/plugins/pom.xml @@ -13,7 +13,6 @@ org.jenkins-ci.plugins plugin 2.33 - diff --git a/jhipster-5/bookstore-monolith/pom.xml b/jhipster-5/bookstore-monolith/pom.xml index 8403c2d1d4..411de0e712 100644 --- a/jhipster-5/bookstore-monolith/pom.xml +++ b/jhipster-5/bookstore-monolith/pom.xml @@ -1136,7 +1136,7 @@ 3.0.0-M2 2.2.1 3.1.0 - 2.22.1 + 2.22.2 3.2.2 0.9.11 1.6 diff --git a/jhipster/jhipster-microservice/gateway-app/src/test/java/com/gateway/web/rest/AccountResourceIntegrationTest.java b/jhipster/jhipster-microservice/gateway-app/src/test/java/com/gateway/web/rest/AccountResourceIntegrationTest.java index 607c69ebd1..6eab576561 100644 --- a/jhipster/jhipster-microservice/gateway-app/src/test/java/com/gateway/web/rest/AccountResourceIntegrationTest.java +++ b/jhipster/jhipster-microservice/gateway-app/src/test/java/com/gateway/web/rest/AccountResourceIntegrationTest.java @@ -26,7 +26,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyObject; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -64,7 +64,7 @@ public class AccountResourceIntegrationTest { @Before public void setup() { MockitoAnnotations.initMocks(this); - doNothing().when(mockMailService).sendActivationEmail(anyObject()); + doNothing().when(mockMailService).sendActivationEmail(any()); AccountResource accountResource = new AccountResource(userRepository, userService, mockMailService); diff --git a/jhipster/jhipster-monolithic/src/test/java/com/baeldung/web/rest/AccountResourceIntegrationTest.java b/jhipster/jhipster-monolithic/src/test/java/com/baeldung/web/rest/AccountResourceIntegrationTest.java index 9644ae488c..a6a104ba63 100644 --- a/jhipster/jhipster-monolithic/src/test/java/com/baeldung/web/rest/AccountResourceIntegrationTest.java +++ b/jhipster/jhipster-monolithic/src/test/java/com/baeldung/web/rest/AccountResourceIntegrationTest.java @@ -26,7 +26,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyObject; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -64,7 +64,7 @@ public class AccountResourceIntegrationTest { @Before public void setup() { MockitoAnnotations.initMocks(this); - doNothing().when(mockMailService).sendActivationEmail(anyObject()); + doNothing().when(mockMailService).sendActivationEmail(any()); AccountResource accountResource = new AccountResource(userRepository, userService, mockMailService); diff --git a/jhipster/jhipster-uaa/gateway/pom.xml b/jhipster/jhipster-uaa/gateway/pom.xml index bc3c9bdef2..536b847237 100644 --- a/jhipster/jhipster-uaa/gateway/pom.xml +++ b/jhipster/jhipster-uaa/gateway/pom.xml @@ -1054,7 +1054,6 @@ 2.10 3.0.0-M2 3.1.0 - 2.22.0 3.2.2 0.9.11 1.6 diff --git a/jhipster/jhipster-uaa/quotes/pom.xml b/jhipster/jhipster-uaa/quotes/pom.xml index 7e4252b309..d922be10c2 100644 --- a/jhipster/jhipster-uaa/quotes/pom.xml +++ b/jhipster/jhipster-uaa/quotes/pom.xml @@ -874,7 +874,6 @@ 2.10 3.0.0-M2 3.1.0 - 2.22.0 3.2.2 0.9.11 0.8.2 diff --git a/jhipster/jhipster-uaa/uaa/pom.xml b/jhipster/jhipster-uaa/uaa/pom.xml index ec4dc1b484..a43da9c366 100644 --- a/jhipster/jhipster-uaa/uaa/pom.xml +++ b/jhipster/jhipster-uaa/uaa/pom.xml @@ -875,7 +875,6 @@ 2.10 3.0.0-M2 3.1.0 - 2.22.0 3.2.2 0.9.11 0.8.2 diff --git a/jjwt/pom.xml b/jjwt/pom.xml index 4c194f9285..cc169ba9fc 100644 --- a/jjwt/pom.xml +++ b/jjwt/pom.xml @@ -38,11 +38,6 @@ jjwt ${jjwt.version} - - org.assertj - assertj-core - test - diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/util/JWTDecoderUtil.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/util/JWTDecoderUtil.java index 922d5c0ce5..0fbf7637dd 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/util/JWTDecoderUtil.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/util/JWTDecoderUtil.java @@ -11,7 +11,7 @@ import static io.jsonwebtoken.SignatureAlgorithm.HS256; public class JWTDecoderUtil { public static String decodeJWTToken(String token) { - Base64.Decoder decoder = Base64.getDecoder(); + Base64.Decoder decoder = Base64.getUrlDecoder(); String[] chunks = token.split("\\."); @@ -22,7 +22,7 @@ public class JWTDecoderUtil { } public static String decodeJWTToken(String token, String secretKey) throws Exception { - Base64.Decoder decoder = Base64.getDecoder(); + Base64.Decoder decoder = Base64.getUrlDecoder(); String[] chunks = token.split("\\."); diff --git a/json-2/README.md b/json-2/README.md index aebc42c472..ed5a79dd3d 100644 --- a/json-2/README.md +++ b/json-2/README.md @@ -8,3 +8,5 @@ This module contains articles about JSON. - [Introduction to Moshi Json](https://www.baeldung.com/java-json-moshi) - [Hypermedia Serialization With JSON-LD](https://www.baeldung.com/json-linked-data) - [Generate a Java Class From JSON](https://www.baeldung.com/java-generate-class-from-json) +- [A Guide to FastJson](https://www.baeldung.com/fastjson) +- More Articles: [[<-- prev]](/json) diff --git a/json-2/pom.xml b/json-2/pom.xml index 53d67320ba..751199d394 100644 --- a/json-2/pom.xml +++ b/json-2/pom.xml @@ -14,6 +14,11 @@ + + com.alibaba + fastjson + ${fastjson.version} + org.jsonschema2pojo jsonschema2pojo-core @@ -24,18 +29,6 @@ jsoniter ${jsoniter.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj-core.version} - test - com.squareup.moshi moshi @@ -153,8 +146,8 @@ 0.9.23 - 3.11.1 1.9.2 + 1.2.21 \ No newline at end of file diff --git a/json/src/test/java/fast_json/FastJsonUnitTest.java b/json-2/src/test/java/com/baeldung/fastjson/FastJsonUnitTest.java similarity index 99% rename from json/src/test/java/fast_json/FastJsonUnitTest.java rename to json-2/src/test/java/com/baeldung/fastjson/FastJsonUnitTest.java index 6fcf1e398a..eec7a1c95f 100644 --- a/json/src/test/java/fast_json/FastJsonUnitTest.java +++ b/json-2/src/test/java/com/baeldung/fastjson/FastJsonUnitTest.java @@ -1,4 +1,4 @@ -package fast_json; +package com.baeldung.fastjson; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; diff --git a/json/src/test/java/fast_json/Person.java b/json-2/src/test/java/com/baeldung/fastjson/Person.java similarity index 97% rename from json/src/test/java/fast_json/Person.java rename to json-2/src/test/java/com/baeldung/fastjson/Person.java index 3d772348a4..5e142131a3 100644 --- a/json/src/test/java/fast_json/Person.java +++ b/json-2/src/test/java/com/baeldung/fastjson/Person.java @@ -1,4 +1,4 @@ -package fast_json; +package com.baeldung.fastjson; import com.alibaba.fastjson.annotation.JSONField; diff --git a/json/README.md b/json/README.md index 6ad4c8a29d..73db055679 100644 --- a/json/README.md +++ b/json/README.md @@ -4,7 +4,6 @@ This module contains articles about JSON. ### Relevant Articles: - [Introduction to JSON Schema in Java](https://www.baeldung.com/introduction-to-json-schema-in-java) -- [A Guide to FastJson](https://www.baeldung.com/fastjson) - [Introduction to JSONForms](https://www.baeldung.com/introduction-to-jsonforms) - [Introduction to JsonPath](https://www.baeldung.com/guide-to-jayway-jsonpath) - [Introduction to JSON-Java (org.json)](https://www.baeldung.com/java-org-json) @@ -14,3 +13,4 @@ This module contains articles about JSON. - [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) - [Escape JSON String in Java](https://www.baeldung.com/java-json-escaping) - [Reducing JSON Data Size](https://www.baeldung.com/json-reduce-data-size) +- More Articles: [[next -->]](../json-2) diff --git a/json/pom.xml b/json/pom.xml index 260b2d1ad9..87bbad460a 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -26,11 +26,6 @@ - - com.alibaba - fastjson - ${fastjson.version} - org.json json @@ -69,23 +64,21 @@ test - org.assertj - assertj-core - ${assertj-core.version} + net.javacrumbs.json-unit + json-unit-assertj + ${json-unit-assertj.version} test 1.4.1 - 1.2.21 1.0 - 4.1 1.0.1 - 20171018 + 20211205 2.8.5 1.1.2 - 3.11.1 + 2.28.0 \ No newline at end of file diff --git a/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java index 441c71e78e..4698b29c6e 100644 --- a/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java @@ -1,36 +1,44 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; - import org.json.CDL; import org.json.JSONArray; import org.json.JSONTokener; import org.junit.Test; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static org.assertj.core.api.Assertions.assertThat; + public class CDLIntegrationTest { + @Test public void givenCommaDelimitedText_thenConvertToJSONArray() { JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada")); - assertEquals("[\"England\",\"USA\",\"Canada\"]", ja.toString()); + + assertThatJson(ja) + .isEqualTo("[\"England\",\"USA\",\"Canada\"]"); } @Test public void givenJSONArray_thenConvertToCommaDelimitedText() { JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]"); + String cdt = CDL.rowToString(ja); - assertEquals("England,USA,Canada", cdt.toString().trim()); + + assertThat(cdt.trim()).isEqualTo("England,USA,Canada"); } @Test public void givenCommaDelimitedText_thenGetJSONArrayOfJSONObjects() { - String string = + String string = "name, city, age \n" + "john, chicago, 22 \n" + "gary, florida, 35 \n" + "sal, vegas, 18"; - + JSONArray result = CDL.toJSONArray(string); - assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString()); + + assertThatJson(result) + .isEqualTo("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]"); } @Test @@ -39,14 +47,16 @@ public class CDLIntegrationTest { ja.put("name"); ja.put("city"); ja.put("age"); - - String string = + + String string = "john, chicago, 22 \n" + "gary, florida, 35 \n" + "sal, vegas, 18"; - + JSONArray result = CDL.toJSONArray(ja, string); - assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString()); + + assertThatJson(result) + .isEqualTo("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]"); } - + } diff --git a/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java index c1a3505bbc..accb94e732 100644 --- a/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java @@ -1,20 +1,23 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static org.assertj.core.api.Assertions.assertThat; import org.json.Cookie; import org.json.JSONObject; import org.junit.Test; public class CookieIntegrationTest { + @Test public void givenCookieString_thenConvertToJSONObject() { String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/"; JSONObject cookieJO = Cookie.toJSONObject(cookie); - assertEquals("{\"path\":\"/\",\"expires\":\"Thu, 18 Dec 2013 12:00:00 UTC\",\"name\":\"username\",\"value\":\"John Doe\"}", cookieJO.toString()); + assertThatJson(cookieJO) + .isEqualTo("{\"path\":\"/\",\"expires\":\"Thu, 18 Dec 2013 12:00:00 UTC\",\"name\":\"username\",\"value\":\"John Doe\"}"); } - + @Test public void givenJSONObject_thenConvertToCookieString() { JSONObject cookieJO = new JSONObject(); @@ -22,8 +25,10 @@ public class CookieIntegrationTest { cookieJO.put("value", "John Doe"); cookieJO.put("expires", "Thu, 18 Dec 2013 12:00:00 UTC"); cookieJO.put("path", "/"); + String cookie = Cookie.toString(cookieJO); - assertEquals("username=John Doe;expires=Thu, 18 Dec 2013 12:00:00 UTC;path=/", cookie.toString()); + assertThat(cookie.split(";")) + .containsExactlyInAnyOrder("username=John Doe", "path=/", "expires=Thu, 18 Dec 2013 12:00:00 UTC"); } } diff --git a/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java index 1aa0427c7e..ad84c22cca 100644 --- a/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java @@ -1,10 +1,12 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; import org.json.HTTP; import org.json.JSONObject; import org.junit.Test; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static org.assertj.core.api.Assertions.assertThat; + public class HTTPIntegrationTest { @Test public void givenJSONObject_thenConvertToHTTPHeader() { @@ -12,14 +14,16 @@ public class HTTPIntegrationTest { jo.put("Method", "POST"); jo.put("Request-URI", "http://www.example.com/"); jo.put("HTTP-Version", "HTTP/1.1"); - - assertEquals("POST \"http://www.example.com/\" HTTP/1.1"+HTTP.CRLF+HTTP.CRLF, HTTP.toString(jo)); + + assertThat(HTTP.toString(jo)) + .isEqualTo("POST \"http://www.example.com/\" HTTP/1.1" + HTTP.CRLF + HTTP.CRLF); } @Test public void givenHTTPHeader_thenConvertToJSONObject() { JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1"); - - assertEquals("{\"Request-URI\":\"http://www.example.com/\",\"Method\":\"POST\",\"HTTP-Version\":\"HTTP/1.1\"}", obj.toString()); + + assertThatJson(obj) + .isEqualTo("{\"Request-URI\":\"http://www.example.com/\",\"Method\":\"POST\",\"HTTP-Version\":\"HTTP/1.1\"}"); } } diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONArrayGetValueByKeyUnitTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONArrayGetValueByKeyUnitTest.java index 265c603acd..7ea22b94ba 100644 --- a/json/src/test/java/com/baeldung/jsonjava/JSONArrayGetValueByKeyUnitTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/JSONArrayGetValueByKeyUnitTest.java @@ -1,12 +1,10 @@ package com.baeldung.jsonjava; -import java.util.Arrays; -import java.util.List; - import org.junit.Test; -import static org.junit.Assert.assertThat; -import static org.hamcrest.CoreMatchers.equalTo; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; public class JSONArrayGetValueByKeyUnitTest { @@ -19,7 +17,8 @@ public class JSONArrayGetValueByKeyUnitTest { List actualValues = obj.getValuesByKeyInJSONArray(jsonStr, "name"); - assertThat(actualValues, equalTo(Arrays.asList("John", "Gary", "Selena"))); + assertThat(actualValues) + .containsExactlyInAnyOrder("John", "Gary", "Selena"); } @Test @@ -29,7 +28,8 @@ public class JSONArrayGetValueByKeyUnitTest { List actualValues = obj.getValuesByKeyInJSONArrayUsingJava8(jsonStr, "name"); - assertThat(actualValues, equalTo(Arrays.asList("John", "Gary", "Selena"))); + assertThat(actualValues) + .containsExactlyInAnyOrder("John", "Gary", "Selena"); } } diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java index c956232abe..eed7779e27 100644 --- a/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java @@ -1,36 +1,40 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - import org.json.JSONArray; import org.json.JSONObject; import org.junit.Test; +import java.util.ArrayList; +import java.util.List; + +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; + public class JSONArrayIntegrationTest { + @Test public void givenJSONJava_thenCreateNewJSONArrayFromScratch() { JSONArray ja = new JSONArray(); ja.put(Boolean.TRUE); ja.put("lorem ipsum"); - + // We can also put a JSONObject in JSONArray JSONObject jo = new JSONObject(); jo.put("name", "jon doe"); jo.put("age", "22"); jo.put("city", "chicago"); - + ja.put(jo); - - assertEquals("[true,\"lorem ipsum\",{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}]", ja.toString()); + + assertThatJson(ja) + .isEqualTo("[true,\"lorem ipsum\",{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}]"); } - + @Test public void givenJsonString_thenCreateNewJSONArray() { JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]"); - assertEquals("[true,\"lorem ipsum\",215]", ja.toString()); + + assertThatJson(ja) + .isEqualTo("[true,\"lorem ipsum\",215]"); } @Test @@ -40,8 +44,10 @@ public class JSONArrayIntegrationTest { list.add("Texas"); list.add("Hawaii"); list.add("Alaska"); - + JSONArray ja = new JSONArray(list); - assertEquals("[\"California\",\"Texas\",\"Hawaii\",\"Alaska\"]", ja.toString()); + + assertThatJson(ja) + .isEqualTo("[\"California\",\"Texas\",\"Hawaii\",\"Alaska\"]"); } } \ No newline at end of file diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java index d8571bfcef..4a435a90d3 100644 --- a/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java @@ -1,23 +1,24 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; - -import java.util.HashMap; -import java.util.Map; - import org.json.JSONObject; import org.junit.Test; +import java.util.HashMap; +import java.util.Map; + +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; + public class JSONObjectIntegrationTest { + @Test public void givenJSONJava_thenCreateNewJSONObject() { JSONObject jo = new JSONObject(); jo.put("name", "jon doe"); jo.put("age", "22"); jo.put("city", "chicago"); - - assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString()); - + + assertThatJson(jo) + .isEqualTo("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"); } @Test @@ -27,8 +28,9 @@ public class JSONObjectIntegrationTest { map.put("age", "22"); map.put("city", "chicago"); JSONObject jo = new JSONObject(map); - - assertEquals("{\"name\":\"jon doe\",\"city\":\"chicago\",\"age\":\"22\"}", jo.toString()); + + assertThatJson(jo) + .isEqualTo("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"); } @Test @@ -36,7 +38,8 @@ public class JSONObjectIntegrationTest { JSONObject jo = new JSONObject( "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}" ); - - assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString()); + + assertThatJson(jo) + .isEqualTo("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"); } } diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java index 4fe8f27231..3bd73ca4c2 100644 --- a/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java @@ -1,21 +1,22 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; - import org.json.JSONTokener; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + public class JSONTokenerIntegrationTest { + @Test public void givenString_convertItToJSONTokens() { String str = "Sample String"; JSONTokener jt = new JSONTokener(str); - + char[] expectedTokens = str.toCharArray(); int index = 0; - - while(jt.more()) { - assertEquals(expectedTokens[index++], jt.next()); + + while (jt.more()) { + assertThat(jt.next()).isEqualTo(expectedTokens[index++]); } } } diff --git a/json/src/test/java/com/baeldung/jsonjava/ObjectToFromJSONIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/ObjectToFromJSONIntegrationTest.java index 99764c5dc9..d1f536d31a 100644 --- a/json/src/test/java/com/baeldung/jsonjava/ObjectToFromJSONIntegrationTest.java +++ b/json/src/test/java/com/baeldung/jsonjava/ObjectToFromJSONIntegrationTest.java @@ -1,19 +1,22 @@ package com.baeldung.jsonjava; -import static org.junit.Assert.assertEquals; - import org.json.JSONObject; import org.junit.Test; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; + public class ObjectToFromJSONIntegrationTest { + @Test public void givenDemoBean_thenCreateJSONObject() { DemoBean demo = new DemoBean(); demo.setId(1); demo.setName("lorem ipsum"); demo.setActive(true); - + JSONObject jo = new JSONObject(demo); - assertEquals("{\"name\":\"lorem ipsum\",\"active\":true,\"id\":1}", jo.toString()); + + assertThatJson(jo) + .isEqualTo("{\"name\":\"lorem ipsum\",\"active\":true,\"id\":1}"); } } diff --git a/guest/webservices/spring-rest-service/src/main/resources/logback.xml b/jta/src/main/resources/resources similarity index 100% rename from guest/webservices/spring-rest-service/src/main/resources/logback.xml rename to jta/src/main/resources/resources diff --git a/jta/src/test/resources/logback-test.xml b/jta/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/jta/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/junit5/README.md b/junit5/README.md deleted file mode 100644 index ad16ad164d..0000000000 --- a/junit5/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## JUnit5 - -This module contains articles about the JUnit 5 - -### Relevant Articles: - diff --git a/junit5/pom.xml b/junit5/pom.xml deleted file mode 100644 index b9804408a2..0000000000 --- a/junit5/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - 4.0.0 - junit5 - junit5 - - - parent-modules - com.baeldung - 1.0.0-SNAPSHOT - - - - 8 - 8 - - - - - org.junit.jupiter - junit-jupiter-api - 5.8.1 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.8.1 - test - - - - \ No newline at end of file diff --git a/junit5/src/test/java/com/baeldung/junit5/A_UnitTest.java b/junit5/src/test/java/com/baeldung/junit5/A_UnitTest.java deleted file mode 100644 index e4ba59b22d..0000000000 --- a/junit5/src/test/java/com/baeldung/junit5/A_UnitTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.junit5; - -import org.junit.jupiter.api.Test; - -public class A_UnitTest { - - @Test - public void first() throws Exception{ - System.out.println("Test A first() start => " + Thread.currentThread().getName()); - Thread.sleep(500); - System.out.println("Test A first() end => " + Thread.currentThread().getName()); - } - - @Test - public void second() throws Exception{ - System.out.println("Test A second() start => " + Thread.currentThread().getName()); - Thread.sleep(500); - System.out.println("Test A second() end => " + Thread.currentThread().getName()); - } - -} diff --git a/junit5/src/test/java/com/baeldung/junit5/B_UnitTest.java b/junit5/src/test/java/com/baeldung/junit5/B_UnitTest.java deleted file mode 100644 index 2b195d2551..0000000000 --- a/junit5/src/test/java/com/baeldung/junit5/B_UnitTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.junit5; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -public class B_UnitTest { - - @Test - public void first() throws Exception{ - System.out.println("Test B first() start => " + Thread.currentThread().getName()); - Thread.sleep(500); - System.out.println("Test B first() end => " + Thread.currentThread().getName()); - } - - @Test - public void second() throws Exception{ - System.out.println("Test B second() start => " + Thread.currentThread().getName()); - Thread.sleep(500); - System.out.println("Test B second() end => " + Thread.currentThread().getName()); - } - -} diff --git a/junit5/src/test/java/com/baeldung/junit5/C_UnitTest.java b/junit5/src/test/java/com/baeldung/junit5/C_UnitTest.java deleted file mode 100644 index ce545f6bee..0000000000 --- a/junit5/src/test/java/com/baeldung/junit5/C_UnitTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.junit5; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.parallel.ResourceLock; - -import java.util.ArrayList; -import java.util.List; - -public class C_UnitTest { - - private List resources; - - @BeforeEach - void before() { - resources = new ArrayList<>(); - resources.add("test"); - } - - @AfterEach - void after() { - resources.clear(); - } - - @Test - @ResourceLock(value = "resources") - public void first() throws Exception { - System.out.println("Test C first() start => " + Thread.currentThread().getName()); - resources.add("first"); - System.out.println(resources); - Thread.sleep(500); - System.out.println("Test C first() end => " + Thread.currentThread().getName()); - } - - @Test - @ResourceLock(value = "resources") - public void second() throws Exception { - System.out.println("Test C second() start => " + Thread.currentThread().getName()); - resources.add("second"); - System.out.println(resources); - Thread.sleep(500); - System.out.println("Test C second() end => " + Thread.currentThread().getName()); - } -} diff --git a/junit5/src/test/resources/junit-platform.properties b/junit5/src/test/resources/junit-platform.properties deleted file mode 100644 index 42100f85da..0000000000 --- a/junit5/src/test/resources/junit-platform.properties +++ /dev/null @@ -1,4 +0,0 @@ -junit.jupiter.execution.parallel.enabled = true -junit.jupiter.execution.parallel.config.strategy=dynamic -junit.jupiter.execution.parallel.mode.default = concurrent -junit.jupiter.execution.parallel.mode.classes.default = concurrent diff --git a/ksqldb/pom.xml b/ksqldb/pom.xml index 2f92419d6e..ee4906090f 100644 --- a/ksqldb/pom.xml +++ b/ksqldb/pom.xml @@ -39,12 +39,6 @@ ${awaitility.version} test - - org.assertj - assertj-core - ${assertj.version} - test - org.testcontainers testcontainers @@ -61,7 +55,6 @@ 6.2.0 - 3.20.2 4.1.0 1.15.3 diff --git a/spring-webflux-threads/src/main/resources/logback.xml b/kubernetes/k8s-admission-controller/src/main/resources/logback.xml similarity index 100% rename from spring-webflux-threads/src/main/resources/logback.xml rename to kubernetes/k8s-admission-controller/src/main/resources/logback.xml diff --git a/kubernetes/k8s-admission-controller/src/test/resources/logback-test.xml b/kubernetes/k8s-admission-controller/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/language-interop/pom.xml b/language-interop/pom.xml index f2b0a08969..57dd8bdd9a 100644 --- a/language-interop/pom.xml +++ b/language-interop/pom.xml @@ -24,12 +24,6 @@ commons-exec ${commons-exec.version} - - org.assertj - assertj-core - ${assertj.version} - test - @@ -49,7 +43,6 @@ 2.7.2 1.3 - 3.6.1 \ No newline at end of file diff --git a/libraries-2/pom.xml b/libraries-2/pom.xml index 700a0a02d4..409363111a 100644 --- a/libraries-2/pom.xml +++ b/libraries-2/pom.xml @@ -39,11 +39,6 @@ parallel-collectors ${parallel-collectors.version} - - org.assertj - assertj-core - ${assertj.version} - io.github.classgraph classgraph @@ -54,7 +49,8 @@ jbpm-test ${jbpm.version} - + junit junit @@ -127,7 +123,6 @@ 3.0.7 - 3.6.2 4.8.28 6.0.0.Final 3.9.6 diff --git a/libraries-3/src/main/resources/logback.xml b/libraries-3/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/libraries-3/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/libraries-3/src/test/resources/logback-test.xml b/libraries-3/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/libraries-3/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/libraries-4/pom.xml b/libraries-4/pom.xml index b16d1f216f..7d19f6d504 100644 --- a/libraries-4/pom.xml +++ b/libraries-4/pom.xml @@ -73,11 +73,6 @@ vavr ${vavr.version} - - org.assertj - assertj-core - ${assertj.version} - org.pcollections pcollections @@ -117,7 +112,6 @@ 2.5 3.2.0-m7 0.9.0 - 3.6.2 2.1.2 3.0.0 0.6.5 diff --git a/libraries-5/pom.xml b/libraries-5/pom.xml index a3ca204995..63d1924852 100644 --- a/libraries-5/pom.xml +++ b/libraries-5/pom.xml @@ -17,11 +17,6 @@ spring-web ${spring.version} - - org.assertj - assertj-core - ${assertj.version} - org.jooq jool @@ -119,7 +114,6 @@ 3.5.0 0.9.12 4.3.8.RELEASE - 3.6.2 2.11 2.5.11 0.6.5 diff --git a/libraries-6/pom.xml b/libraries-6/pom.xml index cecc9ca476..3b932f2bd2 100644 --- a/libraries-6/pom.xml +++ b/libraries-6/pom.xml @@ -74,11 +74,6 @@ commons-net ${commons-net.version} - - org.assertj - assertj-core - ${assertj.version} - commons-io commons-io @@ -148,13 +143,11 @@ 0.12.1 1.15 3.6 - 3.6.2 3.5-beta72 3.0 1.8.1 - 4.4 8.12.9 2.4.4 - + \ No newline at end of file diff --git a/libraries-apache-commons-collections/pom.xml b/libraries-apache-commons-collections/pom.xml index e2805552e3..c1a158b16e 100644 --- a/libraries-apache-commons-collections/pom.xml +++ b/libraries-apache-commons-collections/pom.xml @@ -16,7 +16,7 @@ org.apache.commons commons-collections4 - ${commons.collections.version} + ${commons-collections4.version} org.hamcrest @@ -24,17 +24,9 @@ ${org.hamcrest.java-hamcrest.version} test - - org.assertj - assertj-core - ${assertj.version} - test - - 4.1 - 3.6.2 2.0.0.0 diff --git a/libraries-apache-commons/pom.xml b/libraries-apache-commons/pom.xml index 8fa55c1b0e..9bf6c40e19 100644 --- a/libraries-apache-commons/pom.xml +++ b/libraries-apache-commons/pom.xml @@ -13,11 +13,6 @@ - - org.assertj - assertj-core - ${assertj.version} - commons-beanutils commons-beanutils @@ -69,7 +64,6 @@ 1.1 1.9.3 1.2 - 3.6.2 1.6 3.5.2 3.6.1 diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index 75b2cc962d..146e50b2e1 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -96,11 +96,6 @@ derive4j ${derive4j.version} - - org.assertj - assertj-core - ${assertj.version} - org.slf4j slf4j-api @@ -160,10 +155,8 @@ 4.3.8.RELEASE 4.0.0 1.1.0 - 3.6.2 3.0.0 2.8.4 - 29.0-jre \ No newline at end of file diff --git a/libraries-data-db/pom.xml b/libraries-data-db/pom.xml index 20119da8a2..c0f2848705 100644 --- a/libraries-data-db/pom.xml +++ b/libraries-data-db/pom.xml @@ -63,7 +63,6 @@ com.h2database h2 - ${h2.version} diff --git a/libraries-data-io/pom.xml b/libraries-data-io/pom.xml index 1335ba54d1..713c4342d1 100644 --- a/libraries-data-io/pom.xml +++ b/libraries-data-io/pom.xml @@ -95,12 +95,6 @@ protobuf-java ${google-protobuf.version} - - org.assertj - assertj-core - ${org.assertj.core.version} - test - @@ -110,7 +104,6 @@ 4.1 1.23.0 v4-rev493-1.21.0 - 3.9.0 3.3.5 2.1 2.8.7 diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index 3db34709e7..dd48453a8c 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -14,12 +14,6 @@ - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - org.apache.kafka kafka-streams @@ -92,6 +86,10 @@ commons-codec commons-codec + + junit + junit + @@ -104,6 +102,12 @@ flink-test-utils_2.11 ${flink.version} test + + + junit + junit + + org.slf4j diff --git a/libraries-http/pom.xml b/libraries-http/pom.xml index a00bb4bd39..0ee5f4b290 100644 --- a/libraries-http/pom.xml +++ b/libraries-http/pom.xml @@ -13,11 +13,6 @@ - - org.assertj - assertj-core - ${assertj.version} - com.squareup.okhttp3 @@ -116,7 +111,6 @@ 2.8.5 4.5.3 - 3.6.2 4.9.1 1.23.0 2.2.0 diff --git a/libraries-io/pom.xml b/libraries-io/pom.xml index 0cea9ae9ac..e92f6e11e1 100644 --- a/libraries-io/pom.xml +++ b/libraries-io/pom.xml @@ -32,7 +32,7 @@ net.lingala.zip4j zip4j - 2.9.0 + ${zip4j.version} @@ -41,6 +41,7 @@ 0.1.55 0.27.0 2.4 + 2.9.0 \ No newline at end of file diff --git a/libraries-io/src/main/java/com/baeldung/java/io/zip4j/ZipSingleFile.java b/libraries-io/src/main/java/com/baeldung/java/io/zip4j/ZipSingleFile.java index d0947afa2e..7639a2e9df 100644 --- a/libraries-io/src/main/java/com/baeldung/java/io/zip4j/ZipSingleFile.java +++ b/libraries-io/src/main/java/com/baeldung/java/io/zip4j/ZipSingleFile.java @@ -21,7 +21,7 @@ public class ZipSingleFile { if (!fileToAdd.exists()) { fileToAdd.createNewFile(); } - zipFile.addFile(fileToAdd); + zipFile.addFile(fileToAdd, zipParameters); zipFile.close(); } } diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index 001ecc54a0..6d3bbcd26c 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -48,11 +48,6 @@ bcpkix-jdk15on ${bouncycastle.version} - - org.junit.vintage - junit-vintage-engine - test - org.passay passay diff --git a/libraries-security/src/main/resources/logback.xml b/libraries-security/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/libraries-security/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/libraries-security/src/test/resources/logback-test.xml b/libraries-security/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/libraries-security/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index a9c340b319..66d6295f7c 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -19,12 +19,6 @@ org.eclipse.paho.client.mqttv3 ${eclipse.paho.client.mqttv3.version} - - - org.assertj - assertj-core - ${assertj.version} - org.eclipse.jetty jetty-server @@ -61,12 +55,6 @@ netty-all ${netty.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - org.apache.tomcat @@ -102,7 +90,6 @@ - 3.6.2 4.5.3 9.4.27.v20200227 4.1.20.Final diff --git a/libraries-testing/pom.xml b/libraries-testing/pom.xml index d7b4a88369..4bc6eba7fc 100644 --- a/libraries-testing/pom.xml +++ b/libraries-testing/pom.xml @@ -118,12 +118,6 @@ ${spring-mock-mvc.version} test - - org.assertj - assertj-core - ${assertj.version} - - org.hamcrest java-hamcrest @@ -147,12 +141,6 @@ ${h2.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - net.bytebuddy byte-buddy @@ -206,9 +194,7 @@ 0.8.1 4.3.8.RELEASE 4.1.1 - 3.14.0 2.0.0.0 - 1.4.200 2.7.0 3.14.0 1.8 diff --git a/libraries/pom.xml b/libraries/pom.xml index 4ecf82aa87..7bef56deb0 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -45,12 +45,6 @@ javassist ${javaassist.version} - - - org.assertj - assertj-core - ${assertj.version} - org.javers javers-core @@ -146,12 +140,6 @@ jmh-core ${jmh-core.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - info.debatty java-lsh @@ -179,12 +167,6 @@ google-oauth-client-jetty ${google-api.version} - - org.hamcrest - hamcrest-all - ${hamcrest-all.version} - test - @@ -278,7 +260,6 @@ 0.7.0 3.2.7 1.2 - 3.6.2 3.1.0 2.92 1.9.26 @@ -292,7 +273,6 @@ 1.15 1.23.0 0.9.4.0006L - 1.3 3.2.0-m7 5.1.1 5.0.2 diff --git a/linux-bash/command-line-arguments/src/main/bash/README.md b/linux-bash/command-line-arguments/src/main/bash/README.md index 27d89fff99..015d121617 100644 --- a/linux-bash/command-line-arguments/src/main/bash/README.md +++ b/linux-bash/command-line-arguments/src/main/bash/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [How to Use Command Line Arguments in a Bash Script](https://www.baeldung.com/linux/use-command-line-arguments-in-bash-script) +- [Concatenate Two Strings to Build a Complete Path in Linux](https://www.baeldung.com/linux/concatenate-strings-to-build-path) diff --git a/linux-bash/text/README.md b/linux-bash/text/README.md index 1c27abc8c6..5423ddf916 100644 --- a/linux-bash/text/README.md +++ b/linux-bash/text/README.md @@ -1,4 +1,3 @@ ### Relevant Articles: -- [Linux Commands – Remove All Text After X](https://www.baeldung.com/linux/remove-text-after-x-in-file) - [Linux Commands for Appending Multiple Lines to a File](https://www.baeldung.com/linux/appending-multiple-lines-to-file2) diff --git a/logback-config.xml b/logback-config.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/logback-config.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/logging-modules/flogger/pom.xml b/logging-modules/flogger/pom.xml index b96025f277..c814d31767 100644 --- a/logging-modules/flogger/pom.xml +++ b/logging-modules/flogger/pom.xml @@ -9,7 +9,6 @@ com.baeldung logging-modules 1.0.0-SNAPSHOT - ../pom.xml diff --git a/logging-modules/log-mdc/pom.xml b/logging-modules/log-mdc/pom.xml index a21b9a8fb7..c329a9dbdb 100644 --- a/logging-modules/log-mdc/pom.xml +++ b/logging-modules/log-mdc/pom.xml @@ -94,7 +94,7 @@ - 2.7 + 2.17.1 3.3.6 3.3.0.Final diff --git a/logging-modules/log4j/pom.xml b/logging-modules/log4j/pom.xml index 864e2253b5..ac7c8620cd 100644 --- a/logging-modules/log4j/pom.xml +++ b/logging-modules/log4j/pom.xml @@ -11,7 +11,6 @@ com.baeldung logging-modules 1.0.0-SNAPSHOT - ../pom.xml @@ -47,8 +46,8 @@ 1.2.17 - 2.7 - 2.7 + 2.17.1 + 2.17.1 3.3.6 diff --git a/logging-modules/log4j2/README.md b/logging-modules/log4j2/README.md index 06f218f469..f53df508bf 100644 --- a/logging-modules/log4j2/README.md +++ b/logging-modules/log4j2/README.md @@ -7,3 +7,4 @@ - [Get Log Output in JSON](http://www.baeldung.com/java-log-json-output) - [System.out.println vs Loggers](https://www.baeldung.com/java-system-out-println-vs-loggers) - [Log4j 2 Plugins](https://www.baeldung.com/log4j2-plugins) +- [Printing Thread Info in Log File Using Log4j2](https://www.baeldung.com/log4j2-print-thread-info) diff --git a/logging-modules/log4j2/pom.xml b/logging-modules/log4j2/pom.xml index aaf60a4216..c3a3f4e0f9 100644 --- a/logging-modules/log4j2/pom.xml +++ b/logging-modules/log4j2/pom.xml @@ -10,7 +10,6 @@ com.baeldung logging-modules 1.0.0-SNAPSHOT - ../pom.xml @@ -112,7 +111,7 @@ 2.1.1 - 2.11.0 + 2.17.1 yyyyMMddHHmmss diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2threadinfo/Log4j2ThreadInfo.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2threadinfo/Log4j2ThreadInfo.java new file mode 100644 index 0000000000..2c9b8870e2 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2threadinfo/Log4j2ThreadInfo.java @@ -0,0 +1,18 @@ +package com.baeldung.logging.log4j2threadinfo; + +import java.util.stream.IntStream; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class Log4j2ThreadInfo { + private static final Logger logger = LogManager.getLogger(Log4j2ThreadInfo.class); + + public static void main(String[] args) { + IntStream.range(0, 5).forEach(i -> { + Runnable runnable = () -> logger.info("Logging info"); + Thread thread = new Thread(runnable); + thread.start(); + }); + } +} diff --git a/logging-modules/log4j2/src/main/resources/log4j2.xml b/logging-modules/log4j2/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..6c0bc75a94 --- /dev/null +++ b/logging-modules/log4j2/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} --- thread_id="%tid" thread_name="%tn" thread_priority="%tp" --- [%p] %m%n + + + + + + ${LOG_PATTERN} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logging-modules/logback/pom.xml b/logging-modules/logback/pom.xml index 512dc9e5a3..ab778e954e 100644 --- a/logging-modules/logback/pom.xml +++ b/logging-modules/logback/pom.xml @@ -11,14 +11,13 @@ com.baeldung logging-modules 1.0.0-SNAPSHOT - ../pom.xml org.json json - 20180130 + ${json.version} ch.qos.logback @@ -68,7 +67,43 @@ + + + integration-lite-first + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + integration-lite-second + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + + 20180130 0.1.5 3.3.5 1.4.7 diff --git a/logging-modules/pom.xml b/logging-modules/pom.xml index 7e358ae490..c7a770891d 100644 --- a/logging-modules/pom.xml +++ b/logging-modules/pom.xml @@ -11,7 +11,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../pom.xml diff --git a/lombok-2/README.md b/lombok-2/README.md new file mode 100644 index 0000000000..25d097a7ea --- /dev/null +++ b/lombok-2/README.md @@ -0,0 +1,10 @@ +## Project Lombok + +This module contains articles about Project Lombok. + +### Relevant Articles: + +- [Using Lombok’s @Accessors Annotation](https://www.baeldung.com/lombok-accessors) +- [Declaring Val and Var Variables in Lombok](https://www.baeldung.com/java-lombok-val-var) +- [Lombok Using @With Annotations](https://www.baeldung.com/lombok-with-annotations) +- More articles: [[<-- prev]](../lombok) diff --git a/lombok-2/lombok.config b/lombok-2/lombok.config new file mode 100644 index 0000000000..f68b99fb85 --- /dev/null +++ b/lombok-2/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling = true +lombok.experimental.flagUsage = warning diff --git a/lombok-2/pom.xml b/lombok-2/pom.xml new file mode 100644 index 0000000000..3c67e959a4 --- /dev/null +++ b/lombok-2/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + lombok-2 + 0.1-SNAPSHOT + lombok-2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java similarity index 100% rename from lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java rename to lombok-2/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java diff --git a/lombok-2/src/main/java/com/baeldung/lombok/valvar/ValExample.java b/lombok-2/src/main/java/com/baeldung/lombok/valvar/ValExample.java new file mode 100644 index 0000000000..b7ecd95fa8 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/valvar/ValExample.java @@ -0,0 +1,45 @@ +package com.baeldung.lombok.valvar; + +import lombok.val; +import lombok.var; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class ValExample { + public Class name() { + val name = "name"; + System.out.println("Name: " + name); + return name.getClass(); + } + + public Class age() { + val age = Integer.valueOf(30); + System.out.println("Age: " + age); + return age.getClass(); + } + + public Class listOf() { + val agenda = new ArrayList(); + agenda.add("Day 1"); + System.out.println("Agenda: " + agenda); + return agenda.getClass(); + } + + public Class mapOf() { + val books = new HashMap(); + books.put(1, "Book 1"); + books.put(2, "Book 2"); + System.out.println("Books:"); + for (val entry : books.entrySet()) { + System.out.printf("- %d. %s\n", entry.getKey(), entry.getValue()); + } + return books.getClass(); + } + + public Class compoundTypes(boolean isArray) { + val compound = isArray ? new ArrayList() : new HashSet(); + return compound.getClass(); + } +} diff --git a/lombok-2/src/main/java/com/baeldung/lombok/valvar/VarExample.java b/lombok-2/src/main/java/com/baeldung/lombok/valvar/VarExample.java new file mode 100644 index 0000000000..6fabf66590 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/valvar/VarExample.java @@ -0,0 +1,47 @@ +package com.baeldung.lombok.valvar; + +import lombok.var; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class VarExample { + public String name() { + var name = "name"; + name = "newName"; + System.out.println("Name: " + name); + return name; + } + + public Integer age() { + var age = Integer.valueOf(30); + age = 35; + System.out.println("Age: " + age); + return age; + } + + public ArrayList listOf() { + var agenda = new ArrayList(); + agenda.add("Day 1"); + agenda = new ArrayList(Arrays.asList("Day 2")); + System.out.println("Agenda: " + agenda); + return agenda; + } + + public Map mapOf() { + var books = new HashMap(); + books.put(1, "Book 1"); + books.put(2, "Book 2"); + books = new HashMap(); + books.put(3, "Book 3"); + books.put(4, "Book 4"); + + System.out.println("Books:"); + for (var entry : books.entrySet()) { + System.out.printf("- %d. %s\n", entry.getKey(), entry.getValue()); + } + return books; + } +} diff --git a/lombok-2/src/main/java/com/baeldung/lombok/valvar/lombok.config b/lombok-2/src/main/java/com/baeldung/lombok/valvar/lombok.config new file mode 100644 index 0000000000..be6d5d3694 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/valvar/lombok.config @@ -0,0 +1,2 @@ +lombok.var.flagUsage = warning +lombok.val.flagUsage = warning \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/Device.java b/lombok-2/src/main/java/com/baeldung/lombok/with/Device.java new file mode 100644 index 0000000000..d2c6c33feb --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/Device.java @@ -0,0 +1,13 @@ +package com.baeldung.lombok.with; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.With; + +@Getter +@AllArgsConstructor +public abstract class Device { + private final String serial; + @With + private final boolean isInspected; +} \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/Holder.java b/lombok-2/src/main/java/com/baeldung/lombok/with/Holder.java new file mode 100644 index 0000000000..f379eae0c1 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/Holder.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.with; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.With; + +@Getter +@AllArgsConstructor +public class Holder { + @With + private String variableA; + @With + private String _variableB; + @With + private String $variableC; +} \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/ImprovedUser.java b/lombok-2/src/main/java/com/baeldung/lombok/with/ImprovedUser.java new file mode 100644 index 0000000000..5fafa08eda --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/ImprovedUser.java @@ -0,0 +1,14 @@ +package com.baeldung.lombok.with; + +import lombok.AllArgsConstructor; +import lombok.NonNull; +import lombok.With; + +@With +@AllArgsConstructor +public class ImprovedUser { + @NonNull + private final String username; + @NonNull + private final String emailAddress; +} \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/KioskDevice.java b/lombok-2/src/main/java/com/baeldung/lombok/with/KioskDevice.java new file mode 100644 index 0000000000..de015b69af --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/KioskDevice.java @@ -0,0 +1,13 @@ +package com.baeldung.lombok.with; + +public class KioskDevice extends Device { + + public KioskDevice(String serial, boolean isInspected) { + super(serial, isInspected); + } + + @Override + public Device withInspected(boolean isInspected) { + return new KioskDevice(getSerial(), isInspected); + } +} \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/Stock.java b/lombok-2/src/main/java/com/baeldung/lombok/with/Stock.java new file mode 100644 index 0000000000..33b29737cf --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/Stock.java @@ -0,0 +1,23 @@ +package com.baeldung.lombok.with; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.With; + +@Getter +@AllArgsConstructor +public class Stock { + @With + private String sku; + private int stockCount; + + public Stock withSku(String sku) { + return new Stock("mod-" + sku, stockCount); + } + + public Stock withSKU(String... sku) { + return sku == null || sku.length == 0 ? + new Stock("unknown", stockCount) : + new Stock("mod-" + sku[0], stockCount); + } +} \ No newline at end of file diff --git a/lombok-2/src/main/java/com/baeldung/lombok/with/User.java b/lombok-2/src/main/java/com/baeldung/lombok/with/User.java new file mode 100644 index 0000000000..3aa03d692b --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/with/User.java @@ -0,0 +1,14 @@ +package com.baeldung.lombok.with; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.With; + +@Getter +@AllArgsConstructor +public class User { + private final String username; + private final String emailAddress; + @With + private final boolean isAuthenticated; +} \ No newline at end of file diff --git a/lombok-2/src/main/resources/logback.xml b/lombok-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/lombok-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/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java similarity index 100% rename from lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java rename to lombok-2/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java diff --git a/lombok-2/src/test/java/com/baeldung/lombok/valvar/ValExampleUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/valvar/ValExampleUnitTest.java new file mode 100644 index 0000000000..b8e1102e18 --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/valvar/ValExampleUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.lombok.valvar; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; + +class ValExampleUnitTest { + + @Test + void whenUsingValWithString_thenTheAssignedClassIsCorrect() { + ValExample val = new ValExample(); + assertThat(val.name()).isEqualTo(String.class); + assertThat(val.age()).isEqualTo(Integer.class); + assertThat(val.listOf()).isEqualTo(ArrayList.class); + assertThat(val.mapOf()).isEqualTo(HashMap.class); + assertThat(val.compoundTypes(true)).isEqualTo(ArrayList.class); + assertThat(val.compoundTypes(false)).isEqualTo(HashSet.class); + } + +} \ No newline at end of file diff --git a/lombok-2/src/test/java/com/baeldung/lombok/valvar/VarExampleUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/valvar/VarExampleUnitTest.java new file mode 100644 index 0000000000..de6f76f8bb --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/valvar/VarExampleUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.lombok.valvar; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; + +import static org.assertj.core.api.Assertions.assertThat; + +class VarExampleUnitTest { + + @Test + void whenUsingVarWithString_thenTheAssignedClassIsCorrect() { + VarExample varExample = new VarExample(); + assertThat(varExample.name()).isEqualTo("newName"); + assertThat(varExample.age()).isEqualTo(35); + assertThat("Day 2").isIn(varExample.listOf()); + assertThat(varExample.mapOf()).containsValue("Book 3"); + } + +} \ No newline at end of file diff --git a/lombok-2/src/test/java/com/baeldung/lombok/with/HolderUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/with/HolderUnitTest.java new file mode 100644 index 0000000000..c0a3306a76 --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/with/HolderUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.lombok.with; + + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; + +public class HolderUnitTest { + + @Test + public void whenWithMethodsGenerated_thenUsable() { + Holder value = new Holder("a", "b"); + + Holder valueModifiedA = value.withVariableA("mod-a"); + Holder valueModifiedB = value.with_variableB("mod-b"); + // Holder valueModifiedC = value.with$VariableC("mod-c"); not possible + + assertNotSame(valueModifiedA, value); + assertNotSame(valueModifiedB, value); + assertEquals("mod-a", valueModifiedA.getVariableA()); + assertEquals("mod-b", valueModifiedB.get_variableB()); + } +} diff --git a/lombok-2/src/test/java/com/baeldung/lombok/with/ImprovedUserUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/with/ImprovedUserUnitTest.java new file mode 100644 index 0000000000..b8d466ac4f --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/with/ImprovedUserUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.lombok.with; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ImprovedUserUnitTest { + + @Test + public void whenUsernameNull_thenException() { + ImprovedUser user = new ImprovedUser("testuser", "test@mail.com"); + + assertThrows(NullPointerException.class, () -> user.withUsername(null)); + } + + @Test + public void whenEmailNull_thenException() { + ImprovedUser user = new ImprovedUser("testuser", "test@mail.com"); + + assertThrows(NullPointerException.class, () -> user.withEmailAddress(null)); + } +} \ No newline at end of file diff --git a/lombok-2/src/test/java/com/baeldung/lombok/with/KioskDeviceWithUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/with/KioskDeviceWithUnitTest.java new file mode 100644 index 0000000000..40bd5de8a1 --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/with/KioskDeviceWithUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.lombok.with; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class KioskDeviceWithUnitTest { + + @Test + public void whenDeviceInspected_thenClonedAndUpdated() { + KioskDevice device = new KioskDevice("S-001", false); + + Device inspectedDevice = device.withInspected(true); + + assertNotSame(inspectedDevice, device); + assertFalse(device.isInspected()); + assertTrue(inspectedDevice.isInspected()); + } +} diff --git a/lombok-2/src/test/java/com/baeldung/lombok/with/StockWithUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/with/StockWithUnitTest.java new file mode 100644 index 0000000000..8d757e86ef --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/with/StockWithUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.lombok.with; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class StockWithUnitTest { + + @Test + public void givenWithManuallyProvided_whenSkuChanged_thenManualMethodUsed() { + Stock stock = new Stock("sku-001", 5); + + Stock modifiedStock = stock.withSku("sku-002"); + Stock anotherModifiedStock = stock.withSKU("sku-003", "sku-004"); + + assertNotSame(modifiedStock, stock); + assertNotSame(anotherModifiedStock, stock); + assertTrue(modifiedStock.getSku().startsWith("mod")); + assertTrue(anotherModifiedStock.getSku().startsWith("mod")); + } +} \ No newline at end of file diff --git a/lombok-2/src/test/java/com/baeldung/lombok/with/UserWithUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/with/UserWithUnitTest.java new file mode 100644 index 0000000000..ce32ab9ee3 --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/with/UserWithUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.lombok.with; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class UserWithUnitTest { + + @Test + public void whenUserAuthenticated_thenClonedAndUpdated() { + User immutableUser = new User("testuser", "test@mail.com", false); + + User authenticatedUser = immutableUser.withAuthenticated(true); + + assertNotSame(immutableUser, authenticatedUser); + assertFalse(immutableUser.isAuthenticated()); + assertTrue(authenticatedUser.isAuthenticated()); + } +} \ No newline at end of file diff --git a/lombok/README.md b/lombok/README.md index bda960a28a..a3dcaf8c0b 100644 --- a/lombok/README.md +++ b/lombok/README.md @@ -3,6 +3,7 @@ This module contains articles about Project Lombok. ### Relevant Articles: + - [Introduction to Project Lombok](https://www.baeldung.com/intro-to-project-lombok) - [Using Lombok’s @Builder Annotation](https://www.baeldung.com/lombok-builder) - [Using Lombok’s @Getter for Boolean Fields](https://www.baeldung.com/lombok-getter-boolean) @@ -11,4 +12,6 @@ This module contains articles about Project Lombok. - [Lombok Builder with Custom Setter](https://www.baeldung.com/lombok-builder-custom-setter) - [Setting up Lombok with Eclipse and Intellij](https://www.baeldung.com/lombok-ide) - [Using the @Singular Annotation with Lombok Builders](https://www.baeldung.com/lombok-builder-singular) -- [Using Lombok’s @Accessors Annotation](https://www.baeldung.com/lombok-accessors) +- [Omitting Getter or Setter in Lombok](https://www.baeldung.com/lombok-omit-getter-setter) +- [Lombok Configuration System](https://www.baeldung.com/lombok-configuration-system) +- More articles: [[next -->]](../lombok-2) \ No newline at end of file diff --git a/lombok/lombok.config b/lombok/lombok.config new file mode 100644 index 0000000000..6f1b2fffea --- /dev/null +++ b/lombok/lombok.config @@ -0,0 +1,8 @@ +import lombok_feature.config + +config.stopBubbling = true +lombok.anyconstructor.addconstructorproperties=false +lombok.addLombokGeneratedAnnotation = true +lombok.addSuppressWarnings = false + + diff --git a/lombok/lombok_feature.config b/lombok/lombok_feature.config new file mode 100644 index 0000000000..01b41e1504 --- /dev/null +++ b/lombok/lombok_feature.config @@ -0,0 +1 @@ +lombok.experimental.flagUsage = warning \ No newline at end of file diff --git a/lombok/pom.xml b/lombok/pom.xml index c5758ea8df..d4f89ab4f2 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -17,7 +17,6 @@ org.projectlombok lombok - ${lombok.version} provided @@ -27,10 +26,9 @@ ${hibernate-jpa-2.1-api.version} - org.assertj - assertj-core - ${assertj-core.version} - test + org.jetbrains + annotations + ${annotations.version} @@ -64,20 +62,27 @@ false - + - 1.0.0.Final - - 1.18.10.0 - 3.8.0 + 1.18.20.0 + 23.0.0 \ No newline at end of file diff --git a/lombok/src/main/README.md b/lombok/src/main/README.md deleted file mode 100644 index 4092d8ce99..0000000000 --- a/lombok/src/main/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Guide to the Linux wc Command](https://www.baeldung.com/linux/wc-command) diff --git a/lombok/src/main/java/com/baeldung/lombok/configexamples/Account.java b/lombok/src/main/java/com/baeldung/lombok/configexamples/Account.java new file mode 100644 index 0000000000..2442f9fa4b --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/configexamples/Account.java @@ -0,0 +1,40 @@ +package com.baeldung.lombok.configexamples; + +import lombok.*; +import lombok.extern.java.Log; + +import java.util.logging.Level; + +import static java.lang.Math.abs; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Log +public class Account { + + @NonNull + private Double balance = 0.; + @NonNull + private String accountHolder = ""; + + public Account addBalance(double amount) { + if (amount < 0) { + throw new IllegalArgumentException("Can not add negative amount"); + } + + this.balance += amount; + return this; + } + + public Account withdraw(double amount) { + if (this.balance - abs(amount) < 0) { + domainLog.log(Level.INFO, String.format("Transaction denied for account holder: %s", this.accountHolder)); + throw new IllegalArgumentException(String.format("Not enough balance, you have %.2f", this.balance)); + } + + this.balance -= abs(amount); + return this; + } +} \ No newline at end of file diff --git a/lombok/src/main/java/com/baeldung/lombok/configexamples/TransactionLog.java b/lombok/src/main/java/com/baeldung/lombok/configexamples/TransactionLog.java new file mode 100644 index 0000000000..61a7a94a16 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/configexamples/TransactionLog.java @@ -0,0 +1,13 @@ +package com.baeldung.lombok.configexamples; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@AllArgsConstructor +@Getter +@Accessors(prefix = {"op"}) +public class TransactionLog { + double amount; + String description; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/configexamples/lombok.config b/lombok/src/main/java/com/baeldung/lombok/configexamples/lombok.config new file mode 100644 index 0000000000..824d11a92f --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/configexamples/lombok.config @@ -0,0 +1,6 @@ +clear lombok.experimental.flagUsage + +lombok.anyconstructor.addconstructorproperties=true +lombok.addNullAnnotations = jetbrains +lombok.accessors.chain = true +lombok.log.fieldName = domainLog \ No newline at end of file diff --git a/lombok/src/main/java/com/baeldung/lombok/exclusions/Employee.java b/lombok/src/main/java/com/baeldung/lombok/exclusions/Employee.java new file mode 100644 index 0000000000..60625747a5 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/exclusions/Employee.java @@ -0,0 +1,18 @@ +package com.baeldung.lombok.exclusions; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +@Data +public class Employee { + + @Setter(AccessLevel.NONE) + private String name; + + private String workplace; + + @Getter(AccessLevel.NONE) + private int workLength; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/exclusions/User.java b/lombok/src/main/java/com/baeldung/lombok/exclusions/User.java new file mode 100644 index 0000000000..52ebeab532 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/exclusions/User.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.exclusions; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +public class User { + + @Setter(AccessLevel.NONE) + private long id; + + private String login; + + @Getter(AccessLevel.NONE) + private int age; +} diff --git a/lombok/src/test/java/com/baeldung/lombok/configexamples/AccountUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/configexamples/AccountUnitTest.java new file mode 100644 index 0000000000..c030acf905 --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/configexamples/AccountUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.lombok.configexamples; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AccountUnitTest { + + @Test + void should_initialize_account() { + Account myAccount = new Account() + .setBalance(2000.00) + .setAccountHolder("John Snow"); + + assertEquals(2000.00, myAccount.getBalance()); + assertEquals("John Snow", myAccount.getAccountHolder()); + } + + @Test + void should_throw_error_when_balance_becomes_negative() { + Account myAccount = new Account() + .setBalance(20.00) + .setAccountHolder("John Snow"); + + assertThrows(IllegalArgumentException.class, () -> myAccount.withdraw(100.00)); + } + + @Test + void should_throw_no_error_when_balance_becomes_zero() { + Account myAccount = new Account() + .setBalance(20.00) + .setAccountHolder("John Snow"); + + myAccount.withdraw(20.00); + + assertEquals(0.00, myAccount.getBalance()); + } + + @Test + void should_update_balance_properly() { + Account myAccount = new Account() + .setBalance(20.00) + .setAccountHolder("John Snow"); + + myAccount.withdraw(5.00).withdraw(10.00); + + assertEquals(5.00, myAccount.getBalance()); + } +} \ No newline at end of file diff --git a/mapstruct/pom.xml b/mapstruct/pom.xml index 48687a73b9..4696a46abb 100644 --- a/mapstruct/pom.xml +++ b/mapstruct/pom.xml @@ -41,12 +41,6 @@ lombok-mapstruct-binding ${lombok.mapstruct.binding.version} - - org.assertj - assertj-core - ${assertj.version} - test - @@ -87,7 +81,6 @@ 1.8 1.8 0.2.0 - 3.16.1 \ No newline at end of file diff --git a/maven-archetype/pom.xml b/maven-archetype/pom.xml index 2eab8ac614..04247f622c 100644 --- a/maven-archetype/pom.xml +++ b/maven-archetype/pom.xml @@ -18,7 +18,6 @@ ${archetype-packaging.version} - diff --git a/maven-modules/maven-builder-plugin/pom.xml b/maven-modules/maven-builder-plugin/pom.xml index 2fedee06cc..f7d6a4e69b 100644 --- a/maven-modules/maven-builder-plugin/pom.xml +++ b/maven-modules/maven-builder-plugin/pom.xml @@ -7,12 +7,6 @@ maven-builder-plugin 1.0-SNAPSHOT - - 1.8 - 1.8 - UTF-8 - - @@ -37,4 +31,10 @@ + + 1.8 + 1.8 + UTF-8 + + \ No newline at end of file diff --git a/maven-modules/maven-copy-files/copy-rename-maven-plugin/pom.xml b/maven-modules/maven-copy-files/copy-rename-maven-plugin/pom.xml index 6feb8284e6..06a44ed4fb 100644 --- a/maven-modules/maven-copy-files/copy-rename-maven-plugin/pom.xml +++ b/maven-modules/maven-copy-files/copy-rename-maven-plugin/pom.xml @@ -54,7 +54,7 @@ maven-surefire-plugin - 2.22.1 + 2.22.2 maven-jar-plugin diff --git a/maven-modules/maven-copy-files/maven-antrun-plugin/pom.xml b/maven-modules/maven-copy-files/maven-antrun-plugin/pom.xml index 5168e0e965..b005f4b125 100644 --- a/maven-modules/maven-copy-files/maven-antrun-plugin/pom.xml +++ b/maven-modules/maven-copy-files/maven-antrun-plugin/pom.xml @@ -57,7 +57,7 @@ maven-surefire-plugin - 2.22.1 + 2.22.2 maven-jar-plugin diff --git a/maven-modules/maven-copy-files/maven-resources-plugin/pom.xml b/maven-modules/maven-copy-files/maven-resources-plugin/pom.xml index 6829898b45..a49095f528 100644 --- a/maven-modules/maven-copy-files/maven-resources-plugin/pom.xml +++ b/maven-modules/maven-copy-files/maven-resources-plugin/pom.xml @@ -54,7 +54,7 @@ maven-surefire-plugin - 2.22.1 + 2.22.2 maven-jar-plugin diff --git a/maven-modules/maven-copy-files/pom.xml b/maven-modules/maven-copy-files/pom.xml index 94bf952361..57d0ddf647 100644 --- a/maven-modules/maven-copy-files/pom.xml +++ b/maven-modules/maven-copy-files/pom.xml @@ -51,7 +51,7 @@ maven-surefire-plugin - 2.22.1 + 2.22.2 maven-jar-plugin diff --git a/maven-modules/maven-generate-war/pom.xml b/maven-modules/maven-generate-war/pom.xml index e5b42f5090..56256f58ea 100644 --- a/maven-modules/maven-generate-war/pom.xml +++ b/maven-modules/maven-generate-war/pom.xml @@ -1,62 +1,68 @@ - -4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.5.4 - - - -com.baeldung -maven-generate-war -0.0.1-SNAPSHOT -war -maven-generate-war -Spring boot project to demonstrate war file generation - - 11 - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - - maven-generate-war - - - maven-war-plugin - 3.3.1 - - - - additional_resources - - - - - true - - - - - - - + + 4.0.0 + com.baeldung + maven-generate-war + 0.0.1-SNAPSHOT + war + maven-generate-war + Spring boot project to demonstrate war file generation + + org.springframework.boot + spring-boot-starter-parent + 2.5.4 + + + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + + maven-generate-war + + + maven-war-plugin + 3.3.1 + + + + additional_resources + + + + + true + + + + + + + + + 11 + + + \ No newline at end of file diff --git a/maven-modules/maven-integration-test/pom.xml b/maven-modules/maven-integration-test/pom.xml index 4283baf63b..56c243e3c5 100644 --- a/maven-modules/maven-integration-test/pom.xml +++ b/maven-modules/maven-integration-test/pom.xml @@ -26,12 +26,6 @@ jersey-hk2 ${jersey.version} - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - @@ -92,8 +86,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} DataTest.java @@ -177,8 +171,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} DataTest.java @@ -223,8 +217,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} integration-test @@ -275,7 +269,6 @@ 3.0.2 3.8.0 - 2.22.0 2.22.0 1.1 3.0.0 diff --git a/maven-modules/maven-multi-source/pom.xml b/maven-modules/maven-multi-source/pom.xml index 65e00419af..d9863b31a9 100644 --- a/maven-modules/maven-multi-source/pom.xml +++ b/maven-modules/maven-multi-source/pom.xml @@ -54,8 +54,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} integration-test @@ -81,7 +81,6 @@ 3.0.2 3.8.0 - 2.22.0 2.22.0 1.1 3.0.0 diff --git a/maven-modules/maven-parent-pom-resolution/aggregator/module1/pom.xml b/maven-modules/maven-parent-pom-resolution/aggregator/module1/pom.xml index e1f411db2f..67e60fb386 100644 --- a/maven-modules/maven-parent-pom-resolution/aggregator/module1/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/aggregator/module1/pom.xml @@ -13,4 +13,4 @@ - + \ No newline at end of file diff --git a/maven-modules/maven-parent-pom-resolution/aggregator/module2/module3/pom.xml b/maven-modules/maven-parent-pom-resolution/aggregator/module2/module3/pom.xml index d983f35e3e..f4e3e81e7d 100644 --- a/maven-modules/maven-parent-pom-resolution/aggregator/module2/module3/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/aggregator/module2/module3/pom.xml @@ -15,4 +15,4 @@ ../../pom.xml - + \ No newline at end of file diff --git a/maven-modules/maven-parent-pom-resolution/aggregator/module2/pom.xml b/maven-modules/maven-parent-pom-resolution/aggregator/module2/pom.xml index 48c1ebab9d..9b36ef37fb 100644 --- a/maven-modules/maven-parent-pom-resolution/aggregator/module2/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/aggregator/module2/pom.xml @@ -18,4 +18,4 @@ module3 - + \ No newline at end of file diff --git a/maven-modules/maven-parent-pom-resolution/aggregator/pom.xml b/maven-modules/maven-parent-pom-resolution/aggregator/pom.xml index 8f6e3453a5..dde2c46370 100644 --- a/maven-modules/maven-parent-pom-resolution/aggregator/pom.xml +++ b/maven-modules/maven-parent-pom-resolution/aggregator/pom.xml @@ -19,4 +19,4 @@ module2 - + \ No newline at end of file diff --git a/maven-modules/maven-plugins/pom.xml b/maven-modules/maven-plugins/pom.xml index 29b3b550ea..4aa295c8a8 100644 --- a/maven-modules/maven-plugins/pom.xml +++ b/maven-modules/maven-plugins/pom.xml @@ -84,8 +84,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} DataTest.java @@ -105,8 +105,8 @@ + org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} integration-test @@ -132,7 +132,6 @@ 3.0.2 3.8.0 - 2.22.0 2.22.0 1.1 3.0.0 diff --git a/maven-modules/maven-properties/pom.xml b/maven-modules/maven-properties/pom.xml index b3169a7fb0..88e13a0fb8 100644 --- a/maven-modules/maven-properties/pom.xml +++ b/maven-modules/maven-properties/pom.xml @@ -14,15 +14,6 @@ ../.. - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - - - diff --git a/maven-modules/maven-dependency/README.md b/maven-modules/maven-simple/maven-dependency/README.md similarity index 100% rename from maven-modules/maven-dependency/README.md rename to maven-modules/maven-simple/maven-dependency/README.md diff --git a/maven-modules/maven-dependency/pom.xml b/maven-modules/maven-simple/maven-dependency/pom.xml similarity index 89% rename from maven-modules/maven-dependency/pom.xml rename to maven-modules/maven-simple/maven-dependency/pom.xml index f17998c327..628c1b62d4 100644 --- a/maven-modules/maven-dependency/pom.xml +++ b/maven-modules/maven-simple/maven-dependency/pom.xml @@ -3,14 +3,13 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung maven-dependency 1.0.0-SNAPSHOT pom com.baeldung - maven-modules + maven-simple 0.0.1-SNAPSHOT @@ -19,7 +18,7 @@ org.apache.commons commons-lang3 - 3.12.0 + ${commons-lang3.version} diff --git a/maven-modules/maven-dependency/src/main/java/com/baeldung/Main.java b/maven-modules/maven-simple/maven-dependency/src/main/java/com/baeldung/Main.java similarity index 100% rename from maven-modules/maven-dependency/src/main/java/com/baeldung/Main.java rename to maven-modules/maven-simple/maven-dependency/src/main/java/com/baeldung/Main.java diff --git a/maven-modules/maven-profiles/README.md b/maven-modules/maven-simple/maven-profiles/README.md similarity index 100% rename from maven-modules/maven-profiles/README.md rename to maven-modules/maven-simple/maven-profiles/README.md diff --git a/maven-modules/maven-profiles/pom.xml b/maven-modules/maven-simple/maven-profiles/pom.xml similarity index 100% rename from maven-modules/maven-profiles/pom.xml rename to maven-modules/maven-simple/maven-profiles/pom.xml diff --git a/maven-modules/maven-simple/parent-project/core/pom.xml b/maven-modules/maven-simple/parent-project/core/pom.xml new file mode 100644 index 0000000000..ec25c9ace5 --- /dev/null +++ b/maven-modules/maven-simple/parent-project/core/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + org.baeldung + core + core + + + parent-project + com.baeldung + 1.0-SNAPSHOT + + + diff --git a/maven-modules/maven-simple/parent-project/pom.xml b/maven-modules/maven-simple/parent-project/pom.xml new file mode 100644 index 0000000000..a68f8e63bc --- /dev/null +++ b/maven-modules/maven-simple/parent-project/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + parent-project + 1.0-SNAPSHOT + parent-project + pom + + + com.baeldung + maven-simple + 0.0.1-SNAPSHOT + + + + core + service + webapp + + diff --git a/maven-modules/maven-simple/parent-project/service/pom.xml b/maven-modules/maven-simple/parent-project/service/pom.xml new file mode 100644 index 0000000000..1953ec8638 --- /dev/null +++ b/maven-modules/maven-simple/parent-project/service/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + org.baeldung + service + service + + + parent-project + com.baeldung + 1.0-SNAPSHOT + + + diff --git a/maven-modules/maven-simple/parent-project/webapp/pom.xml b/maven-modules/maven-simple/parent-project/webapp/pom.xml new file mode 100644 index 0000000000..bd13c5aeb8 --- /dev/null +++ b/maven-modules/maven-simple/parent-project/webapp/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + org.baeldung + webapp + webapp + + + parent-project + com.baeldung + 1.0-SNAPSHOT + + + diff --git a/maven-modules/plugin-management/README.md b/maven-modules/maven-simple/plugin-management/README.md similarity index 100% rename from maven-modules/plugin-management/README.md rename to maven-modules/maven-simple/plugin-management/README.md diff --git a/maven-modules/plugin-management/pom.xml b/maven-modules/maven-simple/plugin-management/pom.xml similarity index 96% rename from maven-modules/plugin-management/pom.xml rename to maven-modules/maven-simple/plugin-management/pom.xml index cd75e5dbd0..2fb2d5ed41 100644 --- a/maven-modules/plugin-management/pom.xml +++ b/maven-modules/maven-simple/plugin-management/pom.xml @@ -4,11 +4,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 plugin-management - 0.0.1-SNAPSHOT pom - maven-modules + maven-simple com.baeldung 0.0.1-SNAPSHOT diff --git a/maven-modules/plugin-management/submodule-1/pom.xml b/maven-modules/maven-simple/plugin-management/submodule-1/pom.xml similarity index 100% rename from maven-modules/plugin-management/submodule-1/pom.xml rename to maven-modules/maven-simple/plugin-management/submodule-1/pom.xml diff --git a/maven-modules/plugin-management/submodule-1/src/resources/include.json b/maven-modules/maven-simple/plugin-management/submodule-1/src/resources/include.json similarity index 100% rename from maven-modules/plugin-management/submodule-1/src/resources/include.json rename to maven-modules/maven-simple/plugin-management/submodule-1/src/resources/include.json diff --git a/maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java b/maven-modules/maven-simple/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java similarity index 100% rename from maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java rename to maven-modules/maven-simple/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java diff --git a/maven-modules/plugin-management/submodule-2/pom.xml b/maven-modules/maven-simple/plugin-management/submodule-2/pom.xml similarity index 100% rename from maven-modules/plugin-management/submodule-2/pom.xml rename to maven-modules/maven-simple/plugin-management/submodule-2/pom.xml diff --git a/maven-modules/maven-simple/pom.xml b/maven-modules/maven-simple/pom.xml new file mode 100644 index 0000000000..938e2240f8 --- /dev/null +++ b/maven-modules/maven-simple/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + maven-simple + maven-simple + pom + + + com.baeldung + maven-modules + 0.0.1-SNAPSHOT + + + + maven-profiles + plugin-management + maven-dependency + parent-project + + + \ No newline at end of file diff --git a/maven-modules/maven-surefire-plugin/pom.xml b/maven-modules/maven-surefire-plugin/pom.xml index 98decc69e1..840ffab077 100644 --- a/maven-modules/maven-surefire-plugin/pom.xml +++ b/maven-modules/maven-surefire-plugin/pom.xml @@ -14,4 +14,4 @@ 0.0.1-SNAPSHOT - + \ No newline at end of file diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index 0aadb873e5..21bc0e72e1 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -22,7 +22,6 @@ maven-integration-test maven-multi-source maven-plugins - maven-profiles maven-properties maven-unused-dependencies @@ -34,10 +33,9 @@ maven-printing-plugins maven-builder-plugin host-maven-repo-example - plugin-management maven-surefire-plugin maven-parent-pom-resolution - maven-dependency + maven-simple @@ -57,8 +55,4 @@ - - 5.8.1 - - \ No newline at end of file diff --git a/metrics/README.md b/metrics/README.md index 6050b2b310..d386a2264a 100644 --- a/metrics/README.md +++ b/metrics/README.md @@ -8,3 +8,4 @@ This module contains articles about metrics. - [Introduction to Netflix Servo](https://www.baeldung.com/netflix-servo) - [Quick Guide to Micrometer](https://www.baeldung.com/micrometer) - [@Timed Annotation Using Metrics and AspectJ](https://www.baeldung.com/timed-metrics-aspectj) +- [Guide to Netflix Spectator](https://www.baeldung.com/java-netflix-spectator) diff --git a/metrics/pom.xml b/metrics/pom.xml index 0ba590ceec..abdfb14dc6 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -75,16 +75,10 @@ metrics-aspectj-deps ${metrics-aspectj.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.netflix.spectator spectator-api - 0.132.0 + 1.0.11 @@ -95,8 +89,7 @@ 1.7.1 2.0.7.RELEASE - 3.11.1 1.1.0 - \ No newline at end of file + diff --git a/metrics/src/test/java/com/baeldung/metrics/spectator/SpectatorMetersUnitTest.java b/metrics/src/test/java/com/baeldung/metrics/spectator/SpectatorMetersUnitTest.java new file mode 100644 index 0000000000..d27ffec6af --- /dev/null +++ b/metrics/src/test/java/com/baeldung/metrics/spectator/SpectatorMetersUnitTest.java @@ -0,0 +1,221 @@ +package com.baeldung.metrics.spectator; + +import com.netflix.spectator.api.*; +import com.netflix.spectator.api.patterns.LongTaskTimer; +import com.netflix.spectator.api.patterns.PolledMeter; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SpectatorMetersUnitTest { + @Test + public void spectatorCounterTest(){ + + class MyListProcessor { + private final Counter insertCounter; + private final Counter removeCounter; + List requestList = new ArrayList(); + + private MyListProcessor(Registry registry){ + insertCounter = registry.counter("list.insert.count"); + removeCounter = registry.counter("list.remove.count"); + } + + private void addToList(String element){ + requestList.add(element); + insertCounter.increment(); + } + + private void removeFromList(){ + requestList.remove(0); + removeCounter.increment(); + } + } + + MyListProcessor myListProcessor = new MyListProcessor(new DefaultRegistry()); + myListProcessor.addToList("element1"); + myListProcessor.addToList("element2"); + myListProcessor.addToList("element3"); + myListProcessor.removeFromList(); + + assertEquals(3, myListProcessor.insertCounter.count()); + assertEquals(1, myListProcessor.removeCounter.count()); + + } + + @Test + public void spectatorTimerTest() throws Exception { + + class MyRequestProcessor { + private final Timer requestLatency; + + private MyRequestProcessor(Registry registry) { + requestLatency = registry.timer("app.request.latency"); + } + + private String processRequest(int input) throws Exception { + return requestLatency.record(() -> handleRequest(input)); + + } + + private String handleRequest(int input) throws InterruptedException { + try { + Thread.sleep(input); + return "Done"; + } catch (InterruptedException e) { + e.printStackTrace(); + throw e; + } + } + } + + MyRequestProcessor myRequestProcessor = new MyRequestProcessor(new DefaultRegistry()); + myRequestProcessor.processRequest(3000); + assertEquals(1, myRequestProcessor.requestLatency.count()); + assertThat(myRequestProcessor.requestLatency.totalTime()).isBetween(3000000000L, 4000000000L); + } + + @Test + public void spectatorLongTaskTimerTest() throws Exception { + + class MyRequestProcessor { + private final LongTaskTimer refreshDuration; + private long duration; + + private MyRequestProcessor(Registry registry) { + refreshDuration = LongTaskTimer.get(registry, registry.createId("metadata.refreshDuration")); + } + + private String processRequest(int input) throws Exception { + final long taskId = refreshDuration.start(); + try { + Thread.sleep(input); + return "Done"; + + } catch (InterruptedException e) { + e.printStackTrace(); + throw e; + } finally { + refreshDuration.stop(taskId); + } + + } + } + + MyRequestProcessor myRequestProcessor = new MyRequestProcessor(new DefaultRegistry()); + myRequestProcessor.processRequest(3000); + System.out.println(myRequestProcessor.refreshDuration.measure()); + System.out.println(myRequestProcessor.duration); + System.out.println(myRequestProcessor.refreshDuration.duration()); + } + + @Test + public void spectatorGauges_polledMeter_Test(){ + class MyList { + + private List list = new ArrayList();; + private AtomicInteger listSize = new AtomicInteger(0); + + private MyList(Registry registry) { + PolledMeter.using(registry) + .withName("list.size") + .monitorValue(listSize); + } + + private void addToList(String element){ + list.add(element); + listSize.incrementAndGet(); + } + private void removeFromList(){ + list.remove(0); + listSize.decrementAndGet(); + } + private int size(){ + return list.size(); + } + } + + MyList myList = new MyList(new DefaultRegistry()); + myList.addToList("element1"); + myList.addToList("element2"); + myList.addToList("element3"); + myList.addToList("element4"); + myList.removeFromList(); + assertEquals(myList.size(), myList.listSize.get()); + } + + @Test + public void spectatorGauges_ActiveGauges_Test(){ + class MyList { + + private List list = new ArrayList();; + private AtomicInteger listSize = new AtomicInteger(0); + private Gauge gauge; + + private MyList(Registry registry) { + gauge = registry.gauge("list.size"); + } + + private void addToList(String element){ + list.add(element); + listSize.incrementAndGet(); + gauge.set(listSize.get()); + } + private void removeFromList(){ + list.remove(0); + listSize.decrementAndGet(); + gauge.set(listSize.get()); + } + private int size(){ + return list.size(); + } + } + + MyList myList = new MyList(new DefaultRegistry()); + myList.addToList("element1"); + myList.addToList("element2"); + myList.addToList("element3"); + myList.addToList("element4"); + myList.removeFromList(); + assertEquals(3.0, myList.gauge.value()); + } + + @Test + public void spectatorDistributionSummaryTest() throws Exception { + + class MyRequestProcessor { + private final DistributionSummary distributionSummary; + + private MyRequestProcessor(Registry registry) { + distributionSummary = registry.distributionSummary("app.request.size"); + } + + private void processRequest(String input) throws Exception { + distributionSummary.record((long) input.length()); + handleRequest(); + } + + private void handleRequest() throws InterruptedException { + try { + Thread.sleep(3000); + return; + } catch (InterruptedException e) { + e.printStackTrace(); + throw e; + } + } + } + + MyRequestProcessor myRequestProcessor = new MyRequestProcessor(new DefaultRegistry()); + myRequestProcessor.processRequest("This is my sample input."); + assertEquals(1, myRequestProcessor.distributionSummary.count()); + assertEquals("This is my sample input.".length(), (int) myRequestProcessor.distributionSummary.totalAmount()); + } + +} + diff --git a/micronaut/README.md b/micronaut/README.md index 86ed705a9f..1ab31d0c0c 100644 --- a/micronaut/README.md +++ b/micronaut/README.md @@ -4,3 +4,4 @@ This module contains articles about Micronaut. ### Relevant Articles: - [Introduction to Micronaut Framework](https://www.baeldung.com/micronaut) +- [Micronaut vs. Spring Boot](https://www.baeldung.com/micronaut-vs-spring-boot) diff --git a/micronaut/pom.xml b/micronaut/pom.xml index f36f565a94..a04fc5c99c 100644 --- a/micronaut/pom.xml +++ b/micronaut/pom.xml @@ -64,12 +64,6 @@ ${logback.version} runtime - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - io.projectreactor reactor-core @@ -141,7 +135,8 @@ - com.baeldung.micronaut.helloworld.server.ServerApplication + + com.baeldung.micronaut.vs.springboot.CompareApplication 1.0.0.RC2 1.8 1.3.2 diff --git a/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java new file mode 100644 index 0000000000..4654526b28 --- /dev/null +++ b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java @@ -0,0 +1,9 @@ +package com.baeldung.micronaut.vs.springboot; + +import io.micronaut.runtime.Micronaut; + +public class CompareApplication { + public static void main(String[] args) { + Micronaut.run(CompareApplication.class); + } +} diff --git a/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClient.java b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClient.java new file mode 100644 index 0000000000..4d5c752215 --- /dev/null +++ b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClient.java @@ -0,0 +1,23 @@ +package com.baeldung.micronaut.vs.springboot.client; + +import io.micronaut.http.annotation.Get; +import io.micronaut.http.client.annotation.Client; + +@Client("/math") +public interface ArithmeticClient { + + @Get("/sum/{number1}/{number2}") + String sum(float number1, float number2); + + @Get("/subtract/{number1}/{number2}") + String subtract(float number1, float number2); + + @Get("/multiply/{number1}/{number2}") + String multiply(float number1, float number2); + + @Get("/divide/{number1}/{number2}") + String divide(float number1, float number2); + + @Get("/memory") + String memory(); +} diff --git a/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClientImpl.java b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClientImpl.java new file mode 100644 index 0000000000..6b7ae900be --- /dev/null +++ b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/client/ArithmeticClientImpl.java @@ -0,0 +1,46 @@ +package com.baeldung.micronaut.vs.springboot.client; + +import javax.inject.Singleton; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.RxHttpClient; +import io.micronaut.http.client.annotation.Client; + +@Singleton +public class ArithmeticClientImpl { + private RxHttpClient httpClient; + + public ArithmeticClientImpl(@Client("/") RxHttpClient httpClient) { + this.httpClient = httpClient; + } + + public String sum(float number1, float number2) { + HttpRequest req = HttpRequest.GET("/math/sum/" + number1 + "/" + number2); + return httpClient.retrieve(req) + .blockingFirst(); + } + + public String subtract(float number1, float number2) { + HttpRequest req = HttpRequest.GET("/math/subtract/" + number1 + "/" + number2); + return httpClient.retrieve(req) + .blockingFirst(); + } + + public String multiply(float number1, float number2) { + HttpRequest req = HttpRequest.GET("/math/multiply/" + number1 + "/" + number2); + return httpClient.retrieve(req) + .blockingFirst(); + } + + public String divide(float number1, float number2) { + HttpRequest req = HttpRequest.GET("/math/divide/" + number1 + "/" + number2); + return httpClient.retrieve(req) + .blockingFirst(); + } + + public String memory() { + HttpRequest req = HttpRequest.GET("/math/memory"); + return httpClient.retrieve(req) + .blockingFirst(); + } +} diff --git a/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java new file mode 100644 index 0000000000..5bc0e865e1 --- /dev/null +++ b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java @@ -0,0 +1,58 @@ +package com.baeldung.micronaut.vs.springboot.controller; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; + +import javax.inject.Inject; + +import com.baeldung.micronaut.vs.springboot.service.ArithmeticService; + +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; + +@Controller("/math") +public class ArithmeticController { + @Inject + private ArithmeticService arithmeticService; + + @Get("/sum/{number1}/{number2}") + public float getSum(float number1, float number2) { + return arithmeticService.add(number1, number2); + } + + @Get("/subtract/{number1}/{number2}") + public float getDifference(float number1, float number2) { + return arithmeticService.subtract(number1, number2); + } + + @Get("/multiply/{number1}/{number2}") + public float getMultiplication(float number1, float number2) { + return arithmeticService.multiply(number1, number2); + } + + @Get("/divide/{number1}/{number2}") + public float getDivision(float number1, float number2) { + return arithmeticService.divide(number1, number2); + } + + @Get("/memory") + public String getMemoryStatus() { + MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); + String memoryStats = ""; + + String init = String.format("Initial: %.2f GB \n", (double) memoryBean.getHeapMemoryUsage() + .getInit() / 1073741824); + String usedHeap = String.format("Used: %.2f GB \n", (double) memoryBean.getHeapMemoryUsage() + .getUsed() / 1073741824); + String maxHeap = String.format("Max: %.2f GB \n", (double) memoryBean.getHeapMemoryUsage() + .getMax() / 1073741824); + String committed = String.format("Committed: %.2f GB \n", (double) memoryBean.getHeapMemoryUsage() + .getCommitted() / 1073741824); + memoryStats += init; + memoryStats += usedHeap; + memoryStats += maxHeap; + memoryStats += committed; + + return memoryStats; + } +} diff --git a/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java new file mode 100644 index 0000000000..e0e4680495 --- /dev/null +++ b/micronaut/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java @@ -0,0 +1,25 @@ +package com.baeldung.micronaut.vs.springboot.service; + +import javax.inject.Singleton; + +@Singleton +public class ArithmeticService { + public float add(float number1, float number2) { + return number1 + number2; + } + + public float subtract(float number1, float number2) { + return number1 - number2; + } + + public float multiply(float number1, float number2) { + return number1 * number2; + } + + public float divide(float number1, float number2) { + if (number2 == 0) { + throw new IllegalArgumentException("'number2' cannot be zero"); + } + return number1 / number2; + } +} diff --git a/micronaut/src/test/java/com/baeldung/micronaut/vs/springboot/ArithmeticClientUnitTest.java b/micronaut/src/test/java/com/baeldung/micronaut/vs/springboot/ArithmeticClientUnitTest.java new file mode 100644 index 0000000000..9a1b095d22 --- /dev/null +++ b/micronaut/src/test/java/com/baeldung/micronaut/vs/springboot/ArithmeticClientUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.micronaut.vs.springboot; + +import static org.junit.Assert.assertEquals; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + +import io.micronaut.context.ApplicationContext; +import io.micronaut.runtime.server.EmbeddedServer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.micronaut.vs.springboot.client.ArithmeticClientImpl; + +public class ArithmeticClientUnitTest { + private EmbeddedServer server; + private ArithmeticClientImpl client; + + @Before + public void setup() { + server = ApplicationContext.run(EmbeddedServer.class); + client = server.getApplicationContext() + .getBean(ArithmeticClientImpl.class); + } + + @After + public void cleanup() { + server.stop(); + } + + @Test + public void givenTwoNumbers_whenAdd_thenCorrectAnswerReturned() { + String expected = Float.valueOf(10 + 20).toString(); + assertEquals(expected, client.sum(10, 20)); + } + + @Test + public void givenTwoNumbers_whenSubtract_thenCorrectAnswerReturned() { + String expected = Float.valueOf(20 - 10).toString(); + assertEquals(expected, client.subtract(20, 10)); + } + + @Test + public void givenTwoNumbers_whenMultiply_thenCorrectAnswerReturned() { + String expected = Float.valueOf(10 * 20).toString(); + assertEquals(expected, client.multiply(10, 20)); + } + + @Test + public void givenTwoNumbers_whenDivide_thenCorrectAnswerReturned() { + String expected = Float.valueOf(30 / 10).toString(); + assertEquals(expected, client.divide(30, 10)); + } + + @Test + public void whenMemory_thenCorrectAnswerReturned() { + String expected = "Initial:"; + assertThat(client.memory(), containsString(expected)); + } +} diff --git a/mustache/pom.xml b/mustache/pom.xml index db72e693c1..faa8bfd8a1 100644 --- a/mustache/pom.xml +++ b/mustache/pom.xml @@ -20,10 +20,6 @@ compiler ${mustache.compiler.api.version} - - org.assertj - assertj-core - org.springframework.boot spring-boot-starter-web diff --git a/netty/pom.xml b/netty/pom.xml index 1a33eef92e..817b1f2e70 100644 --- a/netty/pom.xml +++ b/netty/pom.xml @@ -22,13 +22,14 @@ org.conscrypt conscrypt-openjdk-uber - 2.4.0 + ${conscrypt-openjdk-uber.version} 4.1.48.Final + 2.4.0 \ No newline at end of file diff --git a/ninja/pom.xml b/ninja/pom.xml index 1cc13afb15..36a28a0977 100644 --- a/ninja/pom.xml +++ b/ninja/pom.xml @@ -3,10 +3,10 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - ninja - jar com.baeldung + ninja 1.0.0 + jar http://www.ninjaframework.org diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index 8e8dbba54d..b7f33de237 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -58,11 +58,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - @@ -93,11 +88,8 @@ 3.3.0 1.0.22.RELEASE - 2.5.4 + 2.6.3 1.9.1 - - 3.4.0 - 2.22.2 \ No newline at end of file diff --git a/parent-java/pom.xml b/parent-java/pom.xml index 103b5f179c..e7d59f48e3 100644 --- a/parent-java/pom.xml +++ b/parent-java/pom.xml @@ -41,9 +41,7 @@ - 31.0.1-jre 2.3.7 - 2.2 \ No newline at end of file diff --git a/parent-spring-4/pom.xml b/parent-spring-4/pom.xml index e0e91cec9a..a36e1060ed 100644 --- a/parent-spring-4/pom.xml +++ b/parent-spring-4/pom.xml @@ -21,12 +21,6 @@ spring-core ${spring.version} - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index c4446ddda8..b2d581c9c1 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -21,17 +21,11 @@ spring-core ${spring.version} - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - 5.3.9 - 5.2.3.RELEASE + 5.3.16 + 5.6.0 1.5.10.RELEASE diff --git a/patterns/clean-architecture/pom.xml b/patterns/clean-architecture/pom.xml index c36f9b83af..5938b0e596 100644 --- a/patterns/clean-architecture/pom.xml +++ b/patterns/clean-architecture/pom.xml @@ -29,11 +29,6 @@ org.springframework.boot spring-boot-starter-data-jpa - - org.junit.jupiter - junit-jupiter-engine - test - org.springframework.boot spring-boot-starter-test @@ -45,23 +40,10 @@ - - org.mockito - mockito-core - test - org.junit.platform junit-platform-engine - - org.junit.jupiter - junit-jupiter-engine - - - org.junit.jupiter - junit-jupiter-api - org.junit.platform junit-platform-runner @@ -71,7 +53,6 @@ - org.springframework.boot spring-boot-maven-plugin diff --git a/patterns/design-patterns-architectural/pom.xml b/patterns/design-patterns-architectural/pom.xml index 11194a9c92..fe7bd38df8 100644 --- a/patterns/design-patterns-architectural/pom.xml +++ b/patterns/design-patterns-architectural/pom.xml @@ -30,12 +30,6 @@ rest-assured ${rest-assured.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - org.hibernate hibernate-core @@ -50,7 +44,6 @@ - 3.9.1 5.2.16.Final 6.0.6 2.5.3 diff --git a/patterns/design-patterns-behavioral-2/pom.xml b/patterns/design-patterns-behavioral-2/pom.xml index f123a8f2f5..da29575526 100644 --- a/patterns/design-patterns-behavioral-2/pom.xml +++ b/patterns/design-patterns-behavioral-2/pom.xml @@ -14,17 +14,4 @@ 1.0.0-SNAPSHOT - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - 3.12.2 - - \ No newline at end of file diff --git a/patterns/design-patterns-behavioral/pom.xml b/patterns/design-patterns-behavioral/pom.xml index bc032a0f8f..3ddbd6f0fc 100644 --- a/patterns/design-patterns-behavioral/pom.xml +++ b/patterns/design-patterns-behavioral/pom.xml @@ -36,18 +36,11 @@ commons-lang3 ${commons-lang3.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - 16.0.2 3.0.1 - 3.9.1 \ No newline at end of file diff --git a/patterns/design-patterns-creational/pom.xml b/patterns/design-patterns-creational/pom.xml index 21bc13c21c..de854d260e 100644 --- a/patterns/design-patterns-creational/pom.xml +++ b/patterns/design-patterns-creational/pom.xml @@ -26,18 +26,11 @@ jsr305 ${javax.annotations.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - 2.4.1 3.0.2 - 3.9.1 \ No newline at end of file diff --git a/patterns/dip/pom.xml b/patterns/dip/pom.xml index 44062aaede..3618791b97 100644 --- a/patterns/dip/pom.xml +++ b/patterns/dip/pom.xml @@ -14,17 +14,4 @@ 1.0.0-SNAPSHOT - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - - - 3.12.1 - - \ No newline at end of file diff --git a/patterns/enterprise-patterns/pom.xml b/patterns/enterprise-patterns/pom.xml index 5b952b9743..10c07d6d05 100644 --- a/patterns/enterprise-patterns/pom.xml +++ b/patterns/enterprise-patterns/pom.xml @@ -29,7 +29,7 @@ org.springframework.boot spring-boot-starter-test - 2.2.2.RELEASE + ${spring-boot.version} test @@ -62,6 +62,7 @@ 3.7.4 + 2.2.2.RELEASE \ No newline at end of file diff --git a/patterns/hexagonal-architecture/pom.xml b/patterns/hexagonal-architecture/pom.xml index 9dfc113d03..b18bd49aec 100644 --- a/patterns/hexagonal-architecture/pom.xml +++ b/patterns/hexagonal-architecture/pom.xml @@ -36,11 +36,6 @@ - - org.mockito - mockito-core - test - diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java deleted file mode 100644 index de8b2f4793..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.simplehexagonalex; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import com.baeldung.simplehexagonalex.controller.QuoteCliController; -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; - -@SpringBootApplication -public class DailyQuoteMain implements CommandLineRunner { - - private static final Logger LOG = LoggerFactory.getLogger(DailyQuoteMain.class); - @Autowired - private QuoteCliController quoteCliController; - - public static void main(final String[] args) { - - SpringApplication.run(DailyQuoteMain.class, args); - } - - @Override - public void run(String... args) throws Exception { - - QuoteOfTheDay quoteOfTheDay = quoteCliController.getQuote("cliController"); - - LOG.info(quoteOfTheDay.toString()); - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java deleted file mode 100644 index 9ecb2bf822..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.simplehexagonalex.controller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.service.QuoteService; - -@Component -public class QuoteCliController { - - private static final Logger LOG = LoggerFactory.getLogger(QuoteCliController.class); - - @Autowired - private QuoteService quoteService; - - public QuoteOfTheDay getQuote(String userId) { - - LOG.info("Getting quote"); - return quoteService.getQuote(userId); - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java deleted file mode 100644 index 061cff8cec..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.simplehexagonalex.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.service.QuoteService; - -@RestController -@RequestMapping("/quote") -public class QuoteRestController { - - @Autowired - private QuoteService quoteService; - - @GetMapping(path = "/{userId}") - public QuoteOfTheDay getEmployee(@PathVariable("userId") String userId) { - return quoteService.getQuote(userId); - } - -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java deleted file mode 100644 index c74c224c70..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.baeldung.simplehexagonalex.domain; - -import java.util.Objects; - -public class QuoteOfTheDay { - - private String userName; - private String quote; - private String provider; - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getQuote() { - return quote; - } - - public void setQuote(String quote) { - this.quote = quote; - } - - public String getProvider() { - return provider; - } - - public void setProvider(String provider) { - this.provider = provider; - } - - @Override - public int hashCode() { - return Objects.hash(provider, quote, userName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - QuoteOfTheDay other = (QuoteOfTheDay) obj; - return Objects.equals(provider, other.provider) && Objects.equals(quote, other.quote) && Objects.equals(userName, other.userName); - } - - @Override - public String toString() { - return "QuoteOfTheDay [userName=" + userName + ", quote=" + quote + ", provider=" + provider + "]"; - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java deleted file mode 100644 index 7e70cebd12..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.simplehexagonalex.domain.repository; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; - -public interface QuoteOfTheDayFromProvider { - - QuoteOfTheDay getQuote(); -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java deleted file mode 100644 index 16f7015ace..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.simplehexagonalex.domain.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; - -@Service -public class QuoteAggregator implements QuoteService { - - @Autowired - private QuoteOfTheDayFromProvider quoteOfTheDayFromProvider; - - @Override - public QuoteOfTheDay getQuote(String userName) { - - QuoteOfTheDay quoteOfTheDay = quoteOfTheDayFromProvider.getQuote(); - quoteOfTheDay.setUserName(userName); - return quoteOfTheDay; - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java deleted file mode 100644 index 300387a41d..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.simplehexagonalex.domain.service; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; - -public interface QuoteService { - - QuoteOfTheDay getQuote(String userName); -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java deleted file mode 100644 index 0cbbc60726..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; - -import java.util.List; -import java.util.Objects; - -public class ProviderQuote { - - private String quote; - private String length; - private String author; - private List tags; - private String category; - private String language; - private String date; - private String permalink; - private String id; - private String background; - private String title; - - public ProviderQuote() { - - } - - public ProviderQuote(String quote, String length, String author, List tags, String category, String language, String date, String permalink, String id, String background, String title) { - super(); - this.quote = quote; - this.length = length; - this.author = author; - this.tags = tags; - this.category = category; - this.language = language; - this.date = date; - this.permalink = permalink; - this.id = id; - this.background = background; - this.title = title; - } - - public String getQuote() { - return quote; - } - - public String getLength() { - return length; - } - - public String getAuthor() { - return author; - } - - public List getTags() { - return tags; - } - - public String getCategory() { - return category; - } - - public String getLanguage() { - return language; - } - - public String getDate() { - return date; - } - - public String getPermalink() { - return permalink; - } - - public String getId() { - return id; - } - - public String getBackground() { - return background; - } - - public String getTitle() { - return title; - } - - public void setId(String id) { - this.id = id; - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ProviderQuote other = (ProviderQuote) obj; - return Objects.equals(id, other.id); - } - - @Override - public String toString() { - return "TheysaysoQuote [quote=" + quote + ", length=" + length + ", " + "author=" + author + ", tags=" + tags + ", category=" + category + ", language=" + language + ", date=" + date + ", permalink=" + permalink + ", id=" + id + ", background=" - + background + ", title=" + title + "]"; - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java deleted file mode 100644 index ded08f7b18..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; - -import java.net.URI; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; -import com.fasterxml.jackson.databind.ObjectMapper; - -@Service("providerQuoteAdapter") -@Primary -public class ProviderQuoteAdapter implements QuoteOfTheDayFromProvider { - - @Autowired - private Environment env; - - @Override - public QuoteOfTheDay getQuote() { - - QuoteOfTheDay quoteOfTheDay = new QuoteOfTheDay(); - ProviderQuoteEnvelope providerQuote; - try { - providerQuote = getProviderQuote(); - quoteOfTheDay.setQuote(providerQuote.getContents() - .getQuotes() - .get(0) - .getQuote()); - quoteOfTheDay.setProvider(providerQuote.getCopyright() - .getUrl()); - } catch (Exception e) { - quoteOfTheDay.setQuote("Unable to get the quote"); - quoteOfTheDay.setProvider("none"); - } - return quoteOfTheDay; - } - - private ProviderQuoteEnvelope getProviderQuote() throws Exception { - - HttpGet request = new HttpGet(URI.create(env.getProperty("theysayso.quote.provider.url"))); - CloseableHttpClient client = HttpClients.createDefault(); - CloseableHttpResponse response = client.execute(request); - ProviderQuoteEnvelope providersQuote = new ObjectMapper().readValue(response.getEntity() - .getContent(), ProviderQuoteEnvelope.class); - return providersQuote; - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java deleted file mode 100644 index 611549f23d..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; - -import java.util.List; - -public class ProviderQuoteEnvelope { - - private Success success; - private Contents contents; - private String baseurl; - private Copyright copyright; - - public ProviderQuoteEnvelope() { - - } - - public ProviderQuoteEnvelope(Success success, Contents contents, String baseurl, Copyright copyright) { - super(); - this.success = success; - this.contents = contents; - this.baseurl = baseurl; - this.copyright = copyright; - } - - public Success getSuccess() { - return success; - } - - public Contents getContents() { - return contents; - } - - public String getBaseurl() { - return baseurl; - } - - public Copyright getCopyright() { - return copyright; - } - - public class Contents { - private List quotes; - - public List getQuotes() { - return quotes; - } - } - - public class Copyright { - private int year; - private String url; - - public int getYear() { - return year; - } - - public String getUrl() { - return url; - } - } - - public class Success { - private int total; - - public int getTotal() { - return total; - } - } -} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java deleted file mode 100644 index 54c28fc94e..0000000000 --- a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.simplehexagonalex.reposity.mock.quoteadapter; - -import org.springframework.stereotype.Service; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; - -@Service -public class MockQuoteAdapter implements QuoteOfTheDayFromProvider { - - @Override - public QuoteOfTheDay getQuote() { - - QuoteOfTheDay quoteOfTheDay = new QuoteOfTheDay(); - quoteOfTheDay.setQuote("Mock quote of the day"); - quoteOfTheDay.setProvider("Mock Provider"); - - return quoteOfTheDay; - } -} diff --git a/patterns/simplehexagonalexample/src/main/resources/application.properties b/patterns/simplehexagonalexample/src/main/resources/application.properties deleted file mode 100644 index dd9413bfd5..0000000000 --- a/patterns/simplehexagonalexample/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -theysayso.quote.provider.url=https://quotes.rest/qod?language=en \ No newline at end of file diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java deleted file mode 100644 index 602f7ea5d4..0000000000 --- a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import org.junit.jupiter.api.Test; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.reposity.mock.quoteadapter.MockQuoteAdapter; - -public class MockAccessProviderUnitTest { - - @Test - public void givenProvider_whenConnect_thenResponse() throws Exception { - - MockQuoteAdapter provider = new MockQuoteAdapter(); - QuoteOfTheDay quote = provider.getQuote(); - assertNotNull(quote); - assertEquals("Mock quote of the day", quote.getQuote()); - assertEquals("Mock Provider", quote.getProvider()); - } -} diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java deleted file mode 100644 index 47e1dde136..0000000000 --- a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; - -import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; -import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; - -@SpringBootTest -public class PrimaryAccessProviderIntegrationTest { - - @Autowired - @Qualifier("providerQuoteAdapter") - QuoteOfTheDayFromProvider provider; - - @Test - public void whenQuoteProvider_thenResponse() throws Exception { - - QuoteOfTheDay quote = provider.getQuote(); - assertNotNull(quote); - assertThat(quote.getProvider()).contains("theysaidso"); - } -} diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java deleted file mode 100644 index 552b5d51c2..0000000000 --- a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; - -@SpringBootTest -@AutoConfigureMockMvc -public class QuoteRequestIntegrationTest { - - @Autowired - private MockMvc mockMvc; - - @Test - public void whenRestQuoteRequest_thenResponse() throws Exception { - - MvcResult result = this.mockMvc.perform(get("/quote/tester")) - .andDo(print()) - .andExpect(status().isOk()) - .andReturn(); - - String content = result.getResponse() - .getContentAsString(); - - assertThat(content).contains("tester"); - assertThat(content).contains("theysaidso"); - } -} \ No newline at end of file diff --git a/patterns/simplehexagonalexample/src/test/resources/application.properties b/patterns/simplehexagonalexample/src/test/resources/application.properties deleted file mode 100644 index dd9413bfd5..0000000000 --- a/patterns/simplehexagonalexample/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -theysayso.quote.provider.url=https://quotes.rest/qod?language=en \ No newline at end of file diff --git a/pdf/pom.xml b/pdf/pom.xml index 6bd1d97402..4bfc7cb621 100644 --- a/pdf/pom.xml +++ b/pdf/pom.xml @@ -104,8 +104,8 @@ - 2.0.3 - 1.6 + 2.0.25 + 2.0.1 5.5.10 5.5.10 3.15 diff --git a/persistence-modules/apache-derby/README.md b/persistence-modules/apache-derby/README.md new file mode 100644 index 0000000000..502115da5e --- /dev/null +++ b/persistence-modules/apache-derby/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Getting Started With Apache Derby](https://www.baeldung.com/java-apache-derby) diff --git a/persistence-modules/apache-derby/pom.xml b/persistence-modules/apache-derby/pom.xml index 7728bd4d8f..f7f5ca7503 100644 --- a/persistence-modules/apache-derby/pom.xml +++ b/persistence-modules/apache-derby/pom.xml @@ -1,15 +1,15 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + apache-derby + persistence-modules com.baeldung 1.0.0-SNAPSHOT - 4.0.0 - - apache-derby @@ -18,15 +18,12 @@ derby 10.13.1.1 - org.apache.derby derbyclient 10.13.1.1 - - \ No newline at end of file diff --git a/persistence-modules/core-java-persistence-2/README.md b/persistence-modules/core-java-persistence-2/README.md index 7b215bfef1..f245392cb3 100644 --- a/persistence-modules/core-java-persistence-2/README.md +++ b/persistence-modules/core-java-persistence-2/README.md @@ -5,3 +5,4 @@ - [How to Check if a Database Table Exists with JDBC](https://www.baeldung.com/jdbc-check-table-exists) - [Inserting Null Into an Integer Column Using JDBC](https://www.baeldung.com/jdbc-insert-null-into-integer-column) - [A Guide to Auto-Commit in JDBC](https://www.baeldung.com/java-jdbc-auto-commit) +- [JDBC Connection Status](https://www.baeldung.com/jdbc-connection-status) diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml index 15676bf03e..780c1fcfca 100644 --- a/persistence-modules/core-java-persistence-2/pom.xml +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -44,7 +44,6 @@ - 1.4.200 8.4.1.jre11 10.2.0.4.0 8.0.22 diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/connectionstatus/ConnectionValidation.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/connectionstatus/ConnectionValidation.java new file mode 100644 index 0000000000..b6818d25c2 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/connectionstatus/ConnectionValidation.java @@ -0,0 +1,65 @@ +package com.baeldung.connectionstatus; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +public class ConnectionValidation +{ + + public static Connection getConnection() + throws Exception + { + Class.forName("org.h2.Driver"); + String url = "jdbc:h2:mem:testdb"; + return DriverManager.getConnection(url, "user", "password"); + } + + public static void runIfOpened(Connection connection) + throws SQLException + { + if (connection != null && !connection.isClosed()) { + // run sql statements + } + else { + // handle closed connection + } + } + + public static void runIfValid(Connection connection) + throws SQLException + { + // Try to validate connection with a 5 seconds timeout + if (connection.isValid(5)) { + // run sql statements + } + else { + // handle invalid connection + } + } + + public static void runIfConnectionValid(Connection connection) + { + if (isConnectionValid(connection)) { + // run sql statements + } + else { + // handle invalid connection + } + } + + public static boolean isConnectionValid(Connection connection) + { + try { + if (connection != null && !connection.isClosed()) { + // Running a simple validation query + connection.prepareStatement("SELECT 1"); + return true; + } + } + catch (SQLException e) { + // log some useful data here + } + return false; + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/connectionstatus/ConnectionValidationUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/connectionstatus/ConnectionValidationUnitTest.java new file mode 100644 index 0000000000..26356931cc --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/connectionstatus/ConnectionValidationUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.connectionstatus; + +import org.junit.jupiter.api.Test; + +import java.sql.Connection; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ConnectionValidationUnitTest +{ + @Test + void givenConnectionObject_whenCreated_thenIsNotClosed() + throws Exception + { + Connection connection = ConnectionValidation.getConnection(); + assertNotNull(connection); + assertFalse(connection.isClosed()); + } + + @Test + void givenConnectionObject_whenCreated_thenIsValid() + throws Exception + { + Connection connection = ConnectionValidation.getConnection(); + assertTrue(connection.isValid(0)); + } + + @Test + void givenConnectionObject_whenValidated_thenIsValid() + throws Exception + { + Connection connection = ConnectionValidation.getConnection(); + assertTrue(ConnectionValidation.isConnectionValid(connection)); + } + +} diff --git a/persistence-modules/core-java-persistence/pom.xml b/persistence-modules/core-java-persistence/pom.xml index 96f8cef310..5cc1df483f 100644 --- a/persistence-modules/core-java-persistence/pom.xml +++ b/persistence-modules/core-java-persistence/pom.xml @@ -22,12 +22,6 @@ ${postgresql.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -61,8 +55,6 @@ - 1.4.200 - 3.10.0 2.4.0 3.2.0 0.9.5.2 diff --git a/persistence-modules/deltaspike/pom.xml b/persistence-modules/deltaspike/pom.xml index 5003ef9daf..f151255948 100644 --- a/persistence-modules/deltaspike/pom.xml +++ b/persistence-modules/deltaspike/pom.xml @@ -18,8 +18,8 @@ - + junit junit diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml index e5c19915a4..634cd64cca 100644 --- a/persistence-modules/hibernate-annotations/pom.xml +++ b/persistence-modules/hibernate-annotations/pom.xml @@ -45,7 +45,6 @@ 5.4.7.Final - 1.4.200 true 2.1.7.RELEASE 5.4.7.Final diff --git a/persistence-modules/hibernate-enterprise/pom.xml b/persistence-modules/hibernate-enterprise/pom.xml index 1d9ebfc156..18d1a4f3a6 100644 --- a/persistence-modules/hibernate-enterprise/pom.xml +++ b/persistence-modules/hibernate-enterprise/pom.xml @@ -19,12 +19,6 @@ hibernate-core ${hibernate.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -87,7 +81,6 @@ 5.3.7.Final 6.0.6 2.2.3 - 3.8.0 0.9 2.3.4 diff --git a/persistence-modules/hibernate-exceptions/README.md b/persistence-modules/hibernate-exceptions/README.md index 7c4f96280e..2e5a98c2f8 100644 --- a/persistence-modules/hibernate-exceptions/README.md +++ b/persistence-modules/hibernate-exceptions/README.md @@ -4,3 +4,4 @@ - [Hibernate Error “No Persistence Provider for EntityManager”](https://www.baeldung.com/hibernate-no-persistence-provider) - [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) - [Hibernate’s “Object References an Unsaved Transient Instance” Error](https://www.baeldung.com/hibernate-unsaved-transient-instance-error) +- [EntityNotFoundException in Hibernate](https://www.baeldung.com/hibernate-entitynotfoundexception) diff --git a/persistence-modules/hibernate-exceptions/pom.xml b/persistence-modules/hibernate-exceptions/pom.xml index 89e1f4ca7e..cabace17b9 100644 --- a/persistence-modules/hibernate-exceptions/pom.xml +++ b/persistence-modules/hibernate-exceptions/pom.xml @@ -29,6 +29,11 @@ jaxb-api ${jaxb.version} + + com.h2database + h2 + ${h2.version} + diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Category.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Category.java similarity index 100% rename from persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Category.java rename to persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Category.java diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Item.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Item.java similarity index 100% rename from persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Item.java rename to persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/Item.java diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/User.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/User.java similarity index 100% rename from persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitynotfoundexception/User.java rename to persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/entitynotfoundexception/User.java diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/lazyinitialization/HibernateUtil.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/lazyinitialization/HibernateUtil.java index b84a512fd4..911e3f7540 100644 --- a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/lazyinitialization/HibernateUtil.java +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/lazyinitialization/HibernateUtil.java @@ -24,7 +24,7 @@ public class HibernateUtil { settings.put(Environment.USER, "sa"); settings.put(Environment.PASS, ""); settings.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect"); - settings.put(Environment.SHOW_SQL, "true"); + settings.put(Environment.SHOW_SQL, "false"); settings.put(Environment.HBM2DDL_AUTO, "update"); configuration.setProperties(settings); configuration.addAnnotatedClass(User.class); diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java index a40279661f..ace9e57d84 100644 --- a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java @@ -27,7 +27,7 @@ public class HibernateUtil { settings.put(Environment.USER, "sa"); settings.put(Environment.PASS, ""); settings.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect"); - settings.put(Environment.SHOW_SQL, "true"); + settings.put(Environment.SHOW_SQL, "false"); settings.put(Environment.USE_SQL_COMMENTS, "true"); settings.put(Environment.HBM2DDL_AUTO, "update"); configuration.setProperties(settings); diff --git a/persistence-modules/hibernate-exceptions/src/main/resources/META-INF/persistence.xml b/persistence-modules/hibernate-exceptions/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..4e83a57f48 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,23 @@ + + + + EntityManager EntityNotFoundException persistence unit + com.baeldung.hibernate.entitynotfoundexception.Category + com.baeldung.hibernate.entitynotfoundexception.Item + com.baeldung.hibernate.entitynotfoundexception.User + true + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitynotfoundexception/EntityNotFoundExceptionIntegrationTest.java b/persistence-modules/hibernate-exceptions/src/test/java/com/baeldung/hibernate/entitynotfoundexception/EntityNotFoundExceptionIntegrationTest.java similarity index 100% rename from persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitynotfoundexception/EntityNotFoundExceptionIntegrationTest.java rename to persistence-modules/hibernate-exceptions/src/test/java/com/baeldung/hibernate/entitynotfoundexception/EntityNotFoundExceptionIntegrationTest.java diff --git a/persistence-modules/hibernate-jpa/README.md b/persistence-modules/hibernate-jpa/README.md index bb079b1705..5599140732 100644 --- a/persistence-modules/hibernate-jpa/README.md +++ b/persistence-modules/hibernate-jpa/README.md @@ -13,5 +13,4 @@ This module contains articles specific to use of Hibernate as a JPA implementati - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) - [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) -- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) -- [EntityNotFoundException in Hibernate](https://www.baeldung.com/hibernate-entitynotfoundexception) +- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/pom.xml b/persistence-modules/hibernate-jpa/pom.xml index 85bfdac07f..7779a85e79 100644 --- a/persistence-modules/hibernate-jpa/pom.xml +++ b/persistence-modules/hibernate-jpa/pom.xml @@ -45,12 +45,6 @@ spring-boot-starter-test ${spring-boot.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -92,7 +86,6 @@ 5.3.7.Final 8.0.13 2.2.3 - 3.8.0 2.1.7.RELEASE diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml index e895ac6ba9..12b41a4973 100644 --- a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml @@ -120,21 +120,4 @@ - - EntityManager EntityNotFoundException persistence unit - com.baeldung.hibernate.entitynotfoundexception.Category - com.baeldung.hibernate.entitynotfoundexception.Item - com.baeldung.hibernate.entitynotfoundexception.User - true - - - - - - - - - - - \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/test/resources/hibernate-pessimistic-locking.properties b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-pessimistic-locking.properties index 4f1ff5e93a..342f7b0bf5 100644 --- a/persistence-modules/hibernate-jpa/src/test/resources/hibernate-pessimistic-locking.properties +++ b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-pessimistic-locking.properties @@ -1,5 +1,5 @@ hibernate.connection.driver_class=org.h2.Driver -hibernate.connection.url=jdbc:h2:mem:mydb3;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=100;MVCC=FALSE +hibernate.connection.url=jdbc:h2:mem:mydb3;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=100 hibernate.connection.username=sa hibernate.connection.autocommit=true hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/persistence-modules/hibernate-libraries/pom.xml b/persistence-modules/hibernate-libraries/pom.xml index 7d552b262d..031d55c17d 100644 --- a/persistence-modules/hibernate-libraries/pom.xml +++ b/persistence-modules/hibernate-libraries/pom.xml @@ -62,12 +62,6 @@ ${hibernate.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - mysql mysql-connector-java @@ -166,9 +160,7 @@ - 3.15.0 1.6 - 29.0-jre 2.9.7 5.4.14.Final 3.27.0-GA diff --git a/persistence-modules/hibernate-mapping/pom.xml b/persistence-modules/hibernate-mapping/pom.xml index 805402951e..506283a4fb 100644 --- a/persistence-modules/hibernate-mapping/pom.xml +++ b/persistence-modules/hibernate-mapping/pom.xml @@ -29,12 +29,6 @@ hibernate-types-52 ${hibernate-types.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -75,9 +69,9 @@ + 1.4.197 5.4.12.Final 2.10.4 - 3.8.0 6.0.16.Final 3.0.1-b11 1.0.3 diff --git a/persistence-modules/hibernate-queries/pom.xml b/persistence-modules/hibernate-queries/pom.xml index 83b2ea4d00..20c2da9ea9 100644 --- a/persistence-modules/hibernate-queries/pom.xml +++ b/persistence-modules/hibernate-queries/pom.xml @@ -19,12 +19,6 @@ hibernate-core ${hibernate.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -60,7 +54,6 @@ 6.0.6 2.2.3 - 3.8.0 \ No newline at end of file diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExample.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExample.java new file mode 100644 index 0000000000..69aaaae19d --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExample.java @@ -0,0 +1,47 @@ +package com.baeldung.hibernate.scalarmethod; + +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + +public class HibernateScalarExample { + + private Session session; + + public HibernateScalarExample(Session session) { + this.session = session; + } + + public List fetchColumnWithNativeQuery() { + return session.createNativeQuery("SELECT * FROM Student student") + .list(); + } + + public List fetchColumnWithScalar() { + return session.createNativeQuery("SELECT * FROM Student student") + .addScalar("studentId", StandardBasicTypes.LONG) + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("age", StandardBasicTypes.INTEGER) + .list(); + } + + public List fetchLimitedColumnWithScalar() { + return session.createNativeQuery("SELECT * FROM Student student") + .addScalar("name", StandardBasicTypes.STRING) + .list(); + } + + public List fetchColumnWithOverloadedScalar() { + return session.createNativeQuery("SELECT * FROM Student student") + .addScalar("name", StandardBasicTypes.STRING) + .addScalar("age") + .list(); + } + + public Integer fetchAvgAgeWithScalar() { + return (Integer) session.createNativeQuery("SELECT AVG(age) as avgAge FROM Student student") + .addScalar("avgAge") + .uniqueResult(); + } +} diff --git a/persistence-modules/hibernate-queries/src/test/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExampleUnitTest.java b/persistence-modules/hibernate-queries/src/test/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExampleUnitTest.java new file mode 100644 index 0000000000..ca01c5cb84 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/test/java/com/baeldung/hibernate/scalarmethod/HibernateScalarExampleUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.hibernate.scalarmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.List; +import java.util.Random; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.pojo.Student; + +public class HibernateScalarExampleUnitTest { + + private static Session session; + private static Transaction transaction; + private static final int DATA_SIZE = 50000; + private static HibernateScalarExample scalarExample; + + @BeforeClass + public static void setUp() throws IOException { + session = HibernateUtil.getSessionFactory().openSession(); + transaction = session.beginTransaction(); + scalarExample = new HibernateScalarExample(session); + session.createNativeQuery("delete from Student").executeUpdate(); + for (int i = 0; i < DATA_SIZE; i++) { + Student student = new Student("John-" + i, generateRandomAge(5, 24)); + session.persist(student); + } + transaction.commit(); + transaction = session.beginTransaction(); + } + + @AfterClass + public static void tearDown() { + transaction.rollback(); + session.close(); + } + + @Test + public void givenNativeQuery_whenNoScalarUsed_ThenFetchAll() { + List list = scalarExample.fetchColumnWithNativeQuery(); + assertEquals(DATA_SIZE, list.size()); + } + + @Test + public void givenNativeQuery_whenScalarUsed_ThenFetchAll() { + List list = scalarExample.fetchColumnWithScalar(); + assertEquals(DATA_SIZE, list.size()); + } + + @Test + public void givenNativeQuery_whenScalarUsed_ThenFetchLimitedColumns() { + List list = scalarExample.fetchLimitedColumnWithScalar(); + for (String colValue : list) { + assertTrue(colValue.startsWith("John")); + } + } + + @Test + public void givenNativeQuery_whenScalarUsedForSingleResult_ThenSingleValueReturned() { + List list = scalarExample.fetchColumnWithOverloadedScalar(); + for (Object[] colArray : list) { + assertEquals(2, colArray.length); + } + } + + @Test + public void whenScalarUsedForAvgAge_ThenSingleValueReturned() { + Integer avgAge = scalarExample.fetchAvgAgeWithScalar(); + assertEquals(true, (avgAge >= 5 && avgAge <= 24)); + } + + private static int generateRandomAge(int min, int max) { + return new Random().nextInt(max - min + 1) + min; + } +} diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index d46d2c16d4..6bec0d4981 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -19,12 +19,6 @@ hibernate-core ${hibernate.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -66,7 +60,6 @@ 5.4.12.Final 6.0.6 2.2.3 - 3.8.0 \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptor.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptor.java index 1d60ccb6c0..24b06f9b65 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptor.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptor.java @@ -16,7 +16,7 @@ public class CustomInterceptor extends EmptyInterceptor { @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if (entity instanceof User) { - logger.info(((User) entity).toString()); + logger.debug(entity.toString()); } return super.onSave(entity, id, state, propertyNames, types); } @@ -25,7 +25,7 @@ public class CustomInterceptor extends EmptyInterceptor { public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object [] previousState, String[] propertyNames, Type[] types) { if (entity instanceof User) { ((User) entity).setLastModified(new Date()); - logger.info(((User) entity).toString()); + logger.debug(entity.toString()); } return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types); } diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/entity/User.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/entity/User.java index 2b1dbe702b..b627cefa33 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/entity/User.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/entity/User.java @@ -1,7 +1,5 @@ package com.baeldung.hibernate.interceptors.entity; -import java.util.Date; - import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -9,6 +7,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import java.util.Date; @Entity(name = "hbi_user") public class User { diff --git a/persistence-modules/hibernate5/src/main/resources/log4j.properties b/persistence-modules/hibernate5/src/main/resources/log4j.properties new file mode 100644 index 0000000000..2173c5d96f --- /dev/null +++ b/persistence-modules/hibernate5/src/main/resources/log4j.properties @@ -0,0 +1 @@ +log4j.rootLogger=INFO, stdout diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/hilo/HibernateHiloUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/hilo/HibernateHiloUnitTest.java index 9285c30af5..d0eab565df 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/hilo/HibernateHiloUnitTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/hilo/HibernateHiloUnitTest.java @@ -42,9 +42,9 @@ public class HibernateHiloUnitTest { private void configureLogger() { BasicConfigurator.configure(); LogManager.getLogger("org.hibernate").setLevel(Level.ERROR); - LogManager.getLogger("org.hibernate.id.enhanced.SequenceStructure").setLevel(Level.DEBUG); - LogManager.getLogger("org.hibernate.event.internal.AbstractSaveEventListener").setLevel(Level.DEBUG); - LogManager.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG); + LogManager.getLogger("org.hibernate.id.enhanced.SequenceStructure").setLevel(Level.INFO); + LogManager.getLogger("org.hibernate.event.internal.AbstractSaveEventListener").setLevel(Level.INFO); + LogManager.getLogger("org.hibernate.SQL").setLevel(Level.INFO); } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java index 0a4caf032b..217351cd75 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java @@ -1,5 +1,8 @@ package com.baeldung.hibernate.proxy; +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; import org.hibernate.*; import org.hibernate.proxy.HibernateProxy; import org.junit.After; diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-hilo.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-hilo.properties index 60d487c1bd..94f3597f1f 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-hilo.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-hilo.properties @@ -2,7 +2,7 @@ hibernate.connection.driver_class=org.h2.Driver hibernate.connection.url=jdbc:h2:mem:hilo_db;DB_CLOSE_DELAY=-1 hibernate.connection.username=sa hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.c3p0.min_size=5 hibernate.c3p0.max_size=20 diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-interceptors.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-interceptors.properties index 58b55d0a09..e5bb5a36a7 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-interceptors.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-interceptors.properties @@ -5,6 +5,6 @@ hibernate.connection.autocommit=true jdbc.password= hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.current_session_context_class=org.hibernate.context.internal.ThreadLocalSessionContext \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-lifecycle.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-lifecycle.properties index d043b624f2..1a5e6482bf 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-lifecycle.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-lifecycle.properties @@ -5,5 +5,5 @@ hibernate.connection.password= hibernate.connection.autocommit=true hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=validate \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-namingstrategy.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-namingstrategy.properties index f75a35bdfe..263033823c 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-namingstrategy.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-namingstrategy.properties @@ -3,7 +3,7 @@ hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 hibernate.connection.username=sa hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.physical_naming_strategy=com.baeldung.hibernate.namingstrategy.CustomPhysicalNamingStrategy diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-persistjson.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-persistjson.properties index 2cf8ac5b63..2481591fca 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-persistjson.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-persistjson.properties @@ -3,5 +3,5 @@ hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 hibernate.connection.username=sa hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate.properties b/persistence-modules/hibernate5/src/test/resources/hibernate.properties index c14782ce0f..42d8e8564f 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate.properties @@ -5,7 +5,7 @@ hibernate.connection.autocommit=true jdbc.password= hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.c3p0.min_size=5 diff --git a/persistence-modules/java-cassandra/README.md b/persistence-modules/java-cassandra/README.md index 735aabdf62..792ef143ab 100644 --- a/persistence-modules/java-cassandra/README.md +++ b/persistence-modules/java-cassandra/README.md @@ -1,4 +1,6 @@ ### Relevant Articles: + +- [Cassandra Batch in Cassandra Query Language and Java](https://www.baeldung.com/java-cql-cassandra-batch) - [A Guide to Cassandra with Java](http://www.baeldung.com/cassandra-with-java) - [Intro to DataStax Java Driver for Apache Cassandra](https://www.baeldung.com/cassandra-datastax-java-driver) - [CQL Data Types](https://www.baeldung.com/cassandra-data-types) diff --git a/persistence-modules/java-cassandra/pom.xml b/persistence-modules/java-cassandra/pom.xml index ad80fc8a83..6df75edc56 100644 --- a/persistence-modules/java-cassandra/pom.xml +++ b/persistence-modules/java-cassandra/pom.xml @@ -43,6 +43,11 @@ java-driver-query-builder ${datastax-cassandra.version} + + io.netty + netty-transport + ${netty-transport-version} + @@ -50,6 +55,7 @@ 3.1.2 3.1.1.0 4.1.0 + 4.1.71.Final - \ No newline at end of file + diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/Application.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/Application.java new file mode 100644 index 0000000000..598b72338e --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/Application.java @@ -0,0 +1,60 @@ +package com.baeldung.cassandra.batch; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.cassandra.batch.domain.Product; +import com.baeldung.cassandra.batch.repository.KeyspaceRepository; +import com.baeldung.cassandra.batch.repository.ProductRepository; +import com.datastax.oss.driver.api.core.CqlSession; + +public class Application { + + private static final Logger LOG = LoggerFactory.getLogger(Application.class); + + public static void main(String[] args) { + new Application().run(); + } + + public void run() { + CassandraConnector connector = new CassandraConnector(); + connector.connect("127.0.0.1", 9042, "datacenter1"); + CqlSession session = connector.getSession(); + + KeyspaceRepository keyspaceRepository = new KeyspaceRepository(session); + + keyspaceRepository.createKeyspace("testKeyspace", 1); + keyspaceRepository.useKeyspace("testKeyspace"); + + ProductRepository productRepository = new ProductRepository(session); + + productRepository.createProductTable("testKeyspace"); + productRepository.createProductByIdTable("testKeyspace"); + productRepository.createProductByIdTable("testKeyspace"); + Product product = getProduct(); + productRepository.insertProductBatch(product); + + Product productV1 = getProduct(); + Product productV2 = getProduct(); + + productRepository.insertProductVariantBatch(productV1, productV2); + + + List products = productRepository.selectAllProduct("testKeyspace"); + products.forEach(x -> LOG.info(x.toString())); + connector.close(); + } + + private Product getProduct() { + Product product = new Product(); + product.setProductName("Banana"); + product.setDescription("Banana"); + product.setPrice(12f); + + return product; + } +} + + diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/CassandraConnector.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/CassandraConnector.java new file mode 100644 index 0000000000..02d63c62f6 --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/CassandraConnector.java @@ -0,0 +1,31 @@ +package com.baeldung.cassandra.batch; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.CqlSessionBuilder; + +import java.net.InetSocketAddress; + +import org.apache.commons.lang3.StringUtils; + +public class CassandraConnector { + + private CqlSession session; + + public void connect(final String node, final Integer port, final String dataCenter) { + CqlSessionBuilder builder = CqlSession.builder(); + builder.addContactPoint(new InetSocketAddress(node, port)); + if (StringUtils.isNotBlank(dataCenter)) { + builder.withLocalDatacenter(dataCenter); + } + + session = builder.build(); + } + + public CqlSession getSession() { + return this.session; + } + + public void close() { + session.close(); + } +} diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/domain/Product.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/domain/Product.java new file mode 100644 index 0000000000..a787225fae --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/domain/Product.java @@ -0,0 +1,79 @@ +package com.baeldung.cassandra.batch.domain; + +import java.util.UUID; + +public class Product { + + public Product() { + super(); + } + + public Product(UUID productId, UUID variantId, String productName, String description, float price) { + super(); + this.productId = productId; + this.variantId = variantId; + this.productName = productName; + this.description = description; + this.price = price; + } + + public Product(UUID productId, String productName, String description, float price) { + super(); + this.productId = productId; + this.productName = productName; + this.description = description; + this.price = price; + } + + private UUID productId; + private UUID variantId; + private String productName; + private String description; + private float price; + + public UUID getProductId() { + return productId; + } + + public void setProductId(UUID productId) { + this.productId = productId; + } + + public UUID getVariantId() { + return variantId; + } + + public void setVariantId(UUID variantId) { + this.variantId = variantId; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } + + @Override + public String toString() { + return "Product [productId=" + productId + ", variantId=" + variantId + ", productName=" + productName + + ", description=" + description + ", price=" + price + "]"; + } +} diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/KeyspaceRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/KeyspaceRepository.java new file mode 100644 index 0000000000..6d09af0bd3 --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/KeyspaceRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.cassandra.batch.repository; + +import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.CqlSession; + +import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; +import com.datastax.oss.driver.api.querybuilder.schema.CreateKeyspace; + +public class KeyspaceRepository { + private final CqlSession session; + + public KeyspaceRepository(CqlSession session) { + this.session = session; + } + + public void createKeyspace(String keyspaceName, int numberOfReplicas) { + CreateKeyspace createKeyspace = SchemaBuilder.createKeyspace(keyspaceName) + .ifNotExists() + .withSimpleStrategy(numberOfReplicas); + + session.execute(createKeyspace.build()); + } + + public void useKeyspace(String keyspace) { + session.execute("USE " + CqlIdentifier.fromCql(keyspace)); + } +} diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java new file mode 100644 index 0000000000..106db133d1 --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java @@ -0,0 +1,188 @@ +package com.baeldung.cassandra.batch.repository; + +import com.baeldung.cassandra.batch.domain.Product; +import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.DefaultBatchType; +import com.datastax.oss.driver.api.core.cql.PreparedStatement; +import com.datastax.oss.driver.api.core.cql.BatchStatement; +import com.datastax.oss.driver.api.core.cql.BoundStatement; +import com.datastax.oss.driver.api.core.cql.ResultSet; +import com.datastax.oss.driver.api.core.cql.SimpleStatement; +import com.datastax.oss.driver.api.core.type.DataTypes; +import com.datastax.oss.driver.api.querybuilder.QueryBuilder; +import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; +import com.datastax.oss.driver.api.querybuilder.schema.CreateTable; +import com.datastax.oss.driver.api.querybuilder.select.Select; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ProductRepository { + + private static final String PRODUCT_TABLE_NAME = "product"; + private static final String PRODUCT_BY_ID_TABLE_NAME = "product_by_id"; + private static final String PRODUCT_BY_NAME_TABLE_NAME = "product_by_name"; + + private final CqlSession session; + + public ProductRepository(CqlSession session) { + this.session = session; + } + + public void createProductTable(String keyspace) { + CreateTable createTable = SchemaBuilder.createTable(PRODUCT_TABLE_NAME).ifNotExists() + .withPartitionKey("product_id", DataTypes.UUID) + .withClusteringColumn("variant_id", DataTypes.UUID) + .withColumn("product_name", DataTypes.TEXT) + .withColumn("description", DataTypes.TEXT) + .withColumn("price", DataTypes.FLOAT); + + executeStatement(createTable.build(), keyspace); + } + + public void createProductByIdTable(String keyspace) { + CreateTable createTable = SchemaBuilder.createTable(PRODUCT_BY_ID_TABLE_NAME).ifNotExists() + .withPartitionKey("product_id", DataTypes.UUID) + .withColumn("product_name", DataTypes.TEXT) + .withColumn("title", DataTypes.TEXT) + .withColumn("description", DataTypes.TEXT) + .withColumn("price", DataTypes.FLOAT); + + executeStatement(createTable.build(), keyspace); + } + + public void createProductTableByName(String keyspace) { + CreateTable createTable = SchemaBuilder.createTable(PRODUCT_BY_NAME_TABLE_NAME).ifNotExists() + .withPartitionKey("product_name", DataTypes.TEXT) + .withColumn("product_id", DataTypes.UUID) + .withColumn("description", DataTypes.TEXT) + .withColumn("price", DataTypes.FLOAT); + + executeStatement(createTable.build(), keyspace); + } + + /** + * Insert two variant Product into same table using a batch query. + * + * @param Product + */ + public void insertProductVariantBatch(Product productVariant1,Product productVariant2) { + UUID productId = UUID.randomUUID(); + BoundStatement productBoundStatement1 = this.getProductVariantInsertStatement(productVariant1,productId); + BoundStatement productBoundStatement2 = this.getProductVariantInsertStatement(productVariant2,productId); + + BatchStatement batch = BatchStatement.newInstance(DefaultBatchType.UNLOGGED, + productBoundStatement1,productBoundStatement2); + + session.execute(batch); + } + + + /** + * Insert two same Product into related tables using a batch query. + * + * @param book + */ + public void insertProductBatch(Product product) { + UUID productId = UUID.randomUUID(); + + BoundStatement productBoundStatement1 = this.getProductInsertStatement(product,productId,PRODUCT_BY_ID_TABLE_NAME); + BoundStatement productBoundStatement2 = this.getProductInsertStatement(product,productId,PRODUCT_BY_NAME_TABLE_NAME); + + BatchStatement batch = BatchStatement.newInstance(DefaultBatchType.LOGGED, + productBoundStatement1,productBoundStatement2); + + session.execute(batch); + } + + public List selectAllProduct(String keyspace) { + Select select = QueryBuilder.selectFrom(PRODUCT_TABLE_NAME).all(); + + ResultSet resultSet = executeStatement(select.build(), keyspace); + + List result = new ArrayList<>(); + + resultSet.forEach(x -> result.add(new Product(x.getUuid("product_id"), x.getUuid("variant_id"), + x.getString("product_name"), x.getString("description"), x.getFloat("price")))); + + return result; + } + + public List selectAllProductByName(String keyspace) { + Select select = QueryBuilder.selectFrom(PRODUCT_BY_NAME_TABLE_NAME).all(); + + ResultSet resultSet = executeStatement(select.build(), keyspace); + + List result = new ArrayList<>(); + + resultSet.forEach(x -> result.add(new Product(x.getUuid("product_id"), + x.getString("product_name"), x.getString("description"), x.getFloat("price")))); + + return result; + } + + public List selectAllProductById(String keyspace) { + Select select = QueryBuilder.selectFrom(PRODUCT_BY_ID_TABLE_NAME).all(); + + ResultSet resultSet = executeStatement(select.build(), keyspace); + + List result = new ArrayList<>(); + + resultSet.forEach(x -> result.add(new Product(x.getUuid("product_id"), + x.getString("product_name"), x.getString("description"), x.getFloat("price")))); + + return result; + } + + /** + * Delete table. + * + * @param tableName the name of the table to delete. + */ + public void deleteTable(String tableName) { + StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS ").append(tableName); + + final String query = sb.toString(); + session.execute(query); + } + + private ResultSet executeStatement(SimpleStatement statement, String keyspace) { + if (keyspace != null) { + statement.setKeyspace(CqlIdentifier.fromCql(keyspace)); + } + + return session.execute(statement); + } + + private BoundStatement getProductVariantInsertStatement(Product product,UUID productId) { + String insertQuery = new StringBuilder("").append("INSERT INTO ").append(PRODUCT_TABLE_NAME) + .append("(product_id,variant_id,product_name,description,price) ").append("VALUES (").append(":product_id") + .append(", ").append(":variant_id").append(", ").append(":product_name").append(", ") + .append(":description").append(", ").append(":price").append(");").toString(); + + PreparedStatement preparedStatement = session.prepare(insertQuery); + + return preparedStatement.bind(productId, UUID.randomUUID(), + product.getProductName(), + product.getDescription(), + product.getPrice()); + } + + private BoundStatement getProductInsertStatement(Product product,UUID productId,String productTableName) { + String cqlQuery1 = new StringBuilder("").append("INSERT INTO ").append(productTableName) + .append("(product_id,product_name,description,price) ").append("VALUES (").append(":product_id") + .append(", ").append(":product_name").append(", ").append(":description").append(", ") + .append(":price").append(");").toString(); + + PreparedStatement preparedStatement = session.prepare(cqlQuery1); + + return preparedStatement.bind(productId, + product.getProductName(), + product.getDescription(), + product.getPrice()); + } + + +} diff --git a/persistence-modules/java-cassandra/src/test/java/com/baeldung/cassandra/batch/epository/ProductRepositoryIntegrationTest.java b/persistence-modules/java-cassandra/src/test/java/com/baeldung/cassandra/batch/epository/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..55dc3dad9f --- /dev/null +++ b/persistence-modules/java-cassandra/src/test/java/com/baeldung/cassandra/batch/epository/ProductRepositoryIntegrationTest.java @@ -0,0 +1,133 @@ +package com.baeldung.cassandra.batch.epository; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.baeldung.cassandra.batch.CassandraConnector; +import com.baeldung.cassandra.batch.domain.Product; +import com.baeldung.cassandra.batch.repository.KeyspaceRepository; +import com.baeldung.cassandra.batch.repository.ProductRepository; +import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.ColumnDefinition; +import com.datastax.oss.driver.api.core.cql.ResultSet; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ProductRepositoryIntegrationTest { + + private KeyspaceRepository schemaRepository; + + private ProductRepository productRepository; + + private CqlSession session; + + private final String KEYSPACE_NAME = "testBaeldungKeyspace"; + private final String PRODUCT = "product"; + + @BeforeClass + public static void init() throws ConfigurationException, TTransportException, IOException, InterruptedException { + // Start an embedded Cassandra Server + EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L); + } + + @Before + public void connect() { + CassandraConnector client = new CassandraConnector(); + client.connect("127.0.0.1", 9142,"datacenter1"); + session = client.getSession(); + schemaRepository = new KeyspaceRepository(client.getSession()); + schemaRepository.createKeyspace(KEYSPACE_NAME, 1); + schemaRepository.useKeyspace(KEYSPACE_NAME); + productRepository = new ProductRepository(client.getSession()); + } + + @Test + public void whenCreatingAProductTable_thenCreatedCorrectly() { + productRepository.deleteTable(KEYSPACE_NAME); + productRepository.createProductTable(KEYSPACE_NAME); + + ResultSet result = session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + PRODUCT + ";"); + + List colDef = new ArrayList<>(); + + result.getColumnDefinitions().forEach(columnDef -> colDef.add(columnDef)); + List columnNames = colDef.stream().map(ColumnDefinition::getName).map(CqlIdentifier::toString).collect(Collectors.toList()); + assertEquals(columnNames.size(), 5); + assertTrue(columnNames.contains("product_id")); + assertTrue(columnNames.contains("variant_id")); + assertTrue(columnNames.contains("product_name")); + assertTrue(columnNames.contains("description")); + assertTrue(columnNames.contains("price")); + } + + @Test + public void whenCreatingRelatedProductBatch_thenCreatedCorrectly() { + productRepository.deleteTable(KEYSPACE_NAME); + productRepository.createProductTableByName(KEYSPACE_NAME); + productRepository.createProductByIdTable(KEYSPACE_NAME); + + Product product = getTestProduct(); + productRepository.insertProductBatch(product); + List productByIdList = productRepository.selectAllProductById(KEYSPACE_NAME); + List productByNameList = productRepository.selectAllProductByName(KEYSPACE_NAME); + + assertEquals(productByIdList.size(), 1); + assertEquals(productByNameList.size(), 1); + assertEquals(productByIdList.get(0).getProductName(), "Banana"); + assertEquals(productByNameList.get(0).getProductName(), "Banana"); + assertEquals(productByIdList.get(0).getDescription(), "Banana"); + assertEquals(productByNameList.get(0).getDescription(), "Banana"); + assertEquals(productByIdList.get(0).getPrice(), 12f,0f); + assertEquals(productByNameList.get(0).getPrice(), 12f,0f); + } + + @Test + public void whenCreatingMultiVariantProductBatch_thenCreatedCorrectly() { + productRepository.deleteTable(KEYSPACE_NAME); + productRepository.createProductTable(KEYSPACE_NAME); + + Product productV1 = getTestProduct(); + Product productV2 = getTestProduct(); + productRepository.insertProductVariantBatch(productV1, productV2); + List productList = productRepository.selectAllProduct(KEYSPACE_NAME); + + assertEquals(productList.size(), 2); + assertEquals(productList.get(0).getProductName(), "Banana"); + assertEquals(productList.get(1).getProductName(), "Banana"); + assertEquals(productList.get(0).getDescription(), "Banana"); + assertEquals(productList.get(1).getDescription(), "Banana"); + assertEquals(productList.get(0).getPrice(), 12f,0f); + assertEquals(productList.get(1).getPrice(), 12f,0f); + } + + + + @AfterClass + public static void cleanup() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } + + private Product getTestProduct() { + Product product = new Product(); + product.setProductName("Banana"); + product.setDescription("Banana"); + product.setPrice(12f); + + return product; + } +} diff --git a/persistence-modules/java-jpa-2/pom.xml b/persistence-modules/java-jpa-2/pom.xml index 26895f3a87..884142f821 100644 --- a/persistence-modules/java-jpa-2/pom.xml +++ b/persistence-modules/java-jpa-2/pom.xml @@ -58,12 +58,6 @@ querydsl-jpa ${querydsl.version} - - org.assertj - assertj-core - ${assertj.version} - test - @@ -139,7 +133,6 @@ 5.4.14.Final 2.7.4 2.2 - 3.11.1 3.5.1 3.3.3 3.0.0 diff --git a/persistence-modules/java-jpa-3/README.md b/persistence-modules/java-jpa-3/README.md index 202c97a830..aa33644b17 100644 --- a/persistence-modules/java-jpa-3/README.md +++ b/persistence-modules/java-jpa-3/README.md @@ -13,5 +13,4 @@ This module contains articles about the Java Persistence API (JPA) in Java. - [Returning an Auto-Generated Id with JPA](https://www.baeldung.com/jpa-get-auto-generated-id) - [How to Return Multiple Entities In JPA Query](https://www.baeldung.com/jpa-return-multiple-entities) - [Defining Unique Constraints in JPA](https://www.baeldung.com/jpa-unique-constraints) -- [How to Check Field Existence in MongoDB?](https://www.baeldung.com/mongodb-check-field-exists) - [Connecting to a Specific Schema in JDBC](https://www.baeldung.com/jdbc-connect-to-schema) diff --git a/persistence-modules/java-jpa-3/pom.xml b/persistence-modules/java-jpa-3/pom.xml index ad649d58d8..b67b8bf608 100644 --- a/persistence-modules/java-jpa-3/pom.xml +++ b/persistence-modules/java-jpa-3/pom.xml @@ -62,18 +62,6 @@ ${postgresql.version} runtime - - org.assertj - assertj-core - ${assertj.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - org.testcontainers postgresql @@ -100,7 +88,6 @@ 2.7.4 8.0.21 2.2 - 3.11.1 3.5.1 3.3.3 3.0.0 diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md index b79cea6781..fe30c2999e 100644 --- a/persistence-modules/java-mongodb/README.md +++ b/persistence-modules/java-mongodb/README.md @@ -10,5 +10,6 @@ This module contains articles about MongoDB in Java. - [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) - [Introduction to Morphia – Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia) - [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations) -- [MongoDB BSON to JSON](https://www.baeldung.com/bson-to-json) - [BSON to JSON Document Conversion in Java](https://www.baeldung.com/java-convert-bson-to-json) +- [How to Check Field Existence in MongoDB?](https://www.baeldung.com/mongodb-check-field-exists) +- [Get Last Inserted Document ID in MongoDB With Java Driver](https://www.baeldung.com/java-mongodb-last-inserted-id) diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/objectid/RetrieveIdExample.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/objectid/RetrieveIdExample.java new file mode 100644 index 0000000000..74279bbfcd --- /dev/null +++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/objectid/RetrieveIdExample.java @@ -0,0 +1,57 @@ +package com.baeldung.mongo.objectid; + +import java.util.Date; + +import org.bson.Document; +import org.bson.types.ObjectId; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; + +public class RetrieveIdExample { + + public static void main(String[] args) { + + try ( MongoClient mongoClient = new MongoClient("localhost", 27017) ) { + + MongoDatabase database = mongoClient.getDatabase("myMongoDb"); + MongoCollection collection = database.getCollection("example"); + +// Create document with user-generated ID + ObjectId generatedId = new ObjectId(); + + System.out.println(generatedId.toString()); + + Document document = new Document(); + document.put("_id", generatedId); + document.put("name", "Shubham"); + document.put("company", "Baeldung"); + collection.insertOne(document); + +// Check that the ID of the document is still the one we set + System.out.println(document.getObjectId("_id").equals(generatedId)); + + +// Create a second document by injecting the ID in the constructor + + ObjectId generatedId2 = ObjectId.get(); + + Document document2 = new Document("_id", generatedId2); + document2.put("name", "Shubham"); + document2.put("company", "Baeldung"); + collection.insertOne(document2); + + Date creationDate = generatedId.getDate(); + System.out.println(creationDate); + + int timestamp = generatedId.getTimestamp(); + + } catch (Exception e) { + + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/existence.field/FieldExistenceLiveTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/existence/field/FieldExistenceLiveTest.java similarity index 100% rename from persistence-modules/java-mongodb/src/test/java/com/baeldung/existence.field/FieldExistenceLiveTest.java rename to persistence-modules/java-mongodb/src/test/java/com/baeldung/existence/field/FieldExistenceLiveTest.java diff --git a/persistence-modules/jooq/pom.xml b/persistence-modules/jooq/pom.xml index c66be9db77..b9229377ab 100644 --- a/persistence-modules/jooq/pom.xml +++ b/persistence-modules/jooq/pom.xml @@ -45,7 +45,6 @@ 3.13.4 - 1.4.200 \ No newline at end of file diff --git a/persistence-modules/jpa-hibernate-cascade-type/pom.xml b/persistence-modules/jpa-hibernate-cascade-type/pom.xml index 467fe11bc3..fd0ae117c7 100644 --- a/persistence-modules/jpa-hibernate-cascade-type/pom.xml +++ b/persistence-modules/jpa-hibernate-cascade-type/pom.xml @@ -17,12 +17,6 @@ hibernate-core ${hibernate.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - com.h2database h2 @@ -48,7 +42,6 @@ 5.4.3.Final - 3.12.2 6.0.17.Final 3.0.0 3.0.1-b11 diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index c3df8866b1..152e58d57b 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -71,10 +71,12 @@ spring-data-geode spring-data-jpa-annotations spring-data-jpa-crud + spring-data-jpa-crud-2 spring-data-jpa-enterprise spring-data-jpa-filtering spring-data-jpa-query spring-data-jpa-query-2 + spring-data-jpa-query-3 spring-data-jpa-repo spring-data-jpa-repo-2 spring-data-jdbc @@ -97,11 +99,7 @@ 5.2.17.Final - 42.2.20 - - - 2.22.2 \ No newline at end of file diff --git a/persistence-modules/r2dbc/pom.xml b/persistence-modules/r2dbc/pom.xml index ae4ca4d91d..1ce5eb3e96 100644 --- a/persistence-modules/r2dbc/pom.xml +++ b/persistence-modules/r2dbc/pom.xml @@ -63,7 +63,6 @@ 0.8.1.RELEASE - 1.4.200 \ No newline at end of file diff --git a/persistence-modules/r2dbc/src/test/resources/logback-test.xml b/persistence-modules/r2dbc/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/r2dbc/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateJsonDatabaseIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateJsonDatabaseIntegrationTest.java index d077268930..2a17d7ab17 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateJsonDatabaseIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateJsonDatabaseIntegrationTest.java @@ -1,17 +1,9 @@ package io.sirix.tutorial.json; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.access.ResourceConfiguration; @@ -19,27 +11,29 @@ import org.sirix.service.json.serialize.JsonSerializer; import org.sirix.service.json.shredder.JsonShredder; import org.sirix.settings.VersioningType; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + public final class CreateJsonDatabaseIntegrationTest { private static final Path JSON_DIRECTORY = Paths.get("src", "test", "resources", "json"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); - - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); - private static final String COMPLEX_JSON = "{\"problems\":[{\"Diabetes\":[{\"medications\":[{\"medicationsClasses\":[{\"className\":[{\"associatedDrug\":[{\"name\":\"asprin\",\"dose\":\"\",\"strength\":\"500 mg\"}],\"associatedDrug#2\":[{\"name\":\"somethingElse\",\"dose\":\"\",\"strength\":\"500 mg\"}]}],\"className2\":[{\"associatedDrug\":[{\"name\":\"asprin\",\"dose\":\"\",\"strength\":\"500 mg\"}],\"associatedDrug#2\":[{\"name\":\"somethingElse\",\"dose\":\"\",\"strength\":\"500 mg\"}]}]}]}],\"labs\":[{\"missing_field\":\"missing_value\"}]}],\"Asthma\":[{}]}]}"; - @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + private Path databasePath; + + @Before + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "json-database"); } @Test @@ -47,10 +41,10 @@ public final class CreateJsonDatabaseIntegrationTest { final var pathToJsonFile = JSON_DIRECTORY.resolve("complex1.json"); // Create an empty JSON database. - Databases.createJsonDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createJsonDatabase(new DatabaseConfiguration(databasePath)); // Open the database. - try (final var database = Databases.openJsonDatabase(DATABASE_PATH)) { + try (final var database = Databases.openJsonDatabase(databasePath)) { // Create a resource to store a JSON-document. database.createResource(ResourceConfiguration.newBuilder("resource") .useTextCompression(false) diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceAndQueryIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceAndQueryIntegrationTest.java index 88ebff9d21..6e2e4a2315 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceAndQueryIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceAndQueryIntegrationTest.java @@ -1,16 +1,9 @@ package io.sirix.tutorial.json; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.api.ResourceManager; @@ -23,28 +16,29 @@ import org.sirix.axis.temporal.PastAxis; import org.sirix.axis.visitor.VisitorDescendantAxis; import org.sirix.node.immutable.json.ImmutableObjectKeyNode; -public final class CreateVersionedJsonResourceAndQueryIntegrationTest { - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); +import java.nio.file.Path; +import java.nio.file.Paths; - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class CreateVersionedJsonResourceAndQueryIntegrationTest { + + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); + + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "json-database"); } @Test - public void createVersionedResourceAndQueryWithTheVisitoDescendantAxis() throws IOException { - Databases.createJsonDatabase(new DatabaseConfiguration(DATABASE_PATH)); + public void createVersionedResourceAndQueryWithTheVisitoDescendantAxis() { + Databases.createJsonDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openJsonDatabase(DATABASE_PATH)) { + try (final var database = Databases.openJsonDatabase(databasePath)) { VersionedJsonDocumentCreator.create(database); try (final var manager = database.openResourceManager("resource"); diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceIntegrationTest.java index 6f26b135b3..832cfe188f 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/CreateVersionedJsonResourceIntegrationTest.java @@ -1,42 +1,36 @@ package io.sirix.tutorial.json; +import org.brackit.xquery.atomic.QNm; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sirix.access.DatabaseConfiguration; +import org.sirix.access.Databases; + +import java.nio.file.Path; +import java.nio.file.Paths; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.brackit.xquery.atomic.QNm; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sirix.access.DatabaseConfiguration; -import org.sirix.access.Databases; - public final class CreateVersionedJsonResourceIntegrationTest { - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "json-database"); } @Test public void createVersionedDatabaseAndCheckAllRevisions() { - Databases.createJsonDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createJsonDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openJsonDatabase(DATABASE_PATH)) { + try (final var database = Databases.openJsonDatabase(databasePath)) { VersionedJsonDocumentCreator.create(database); // Check first revision. diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/JsonFilterIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/JsonFilterIntegrationTest.java index e230f34650..88a4a05101 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/JsonFilterIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/JsonFilterIntegrationTest.java @@ -1,18 +1,12 @@ package io.sirix.tutorial.json; -import static org.junit.Assert.assertEquals; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.access.ResourceConfiguration; -import org.sirix.api.json.JsonNodeReadOnlyTrx; import org.sirix.axis.DescendantAxis; import org.sirix.axis.IncludeSelf; import org.sirix.axis.filter.FilterAxis; @@ -20,24 +14,23 @@ import org.sirix.axis.filter.json.JsonNameFilter; import org.sirix.service.json.shredder.JsonShredder; import org.sirix.settings.VersioningType; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + public final class JsonFilterIntegrationTest { private static final Path JSON_DIRECTORY = Paths.get("src", "test", "resources", "json"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "json-database"); } @Test @@ -45,10 +38,10 @@ public final class JsonFilterIntegrationTest { final var pathToJsonFile = JSON_DIRECTORY.resolve("complex1.json"); // Create an empty JSON database. - Databases.createJsonDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createJsonDatabase(new DatabaseConfiguration(databasePath)); // Open the database. - try (final var database = Databases.openJsonDatabase(DATABASE_PATH)) { + try (final var database = Databases.openJsonDatabase(databasePath)) { // Create a resource to store a JSON-document. database.createResource(ResourceConfiguration.newBuilder("resource") .useTextCompression(false) @@ -70,7 +63,7 @@ public final class JsonFilterIntegrationTest { final var axis = new DescendantAxis(wtx, IncludeSelf.YES); final var filter = new JsonNameFilter(wtx, "associatedDrug"); - for (var filterAxis = new FilterAxis(axis, filter); filterAxis.hasNext();) { + for (var filterAxis = new FilterAxis<>(axis, filter); filterAxis.hasNext();) { filterAxis.next(); foundTimes++; } diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/SerializeVersionedJsonResourceIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/SerializeVersionedJsonResourceIntegrationTest.java index 07932b0c38..481eddf551 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/SerializeVersionedJsonResourceIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/json/SerializeVersionedJsonResourceIntegrationTest.java @@ -1,6 +1,13 @@ package io.sirix.tutorial.json; -import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sirix.access.DatabaseConfiguration; +import org.sirix.access.Databases; +import org.sirix.api.json.JsonResourceManager; +import org.sirix.service.json.serialize.JsonSerializer; import java.io.IOException; import java.io.StringWriter; @@ -10,39 +17,27 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sirix.access.DatabaseConfiguration; -import org.sirix.access.Databases; -import org.sirix.api.json.JsonResourceManager; -import org.sirix.service.json.serialize.JsonSerializer; +import static org.junit.Assert.assertEquals; public class SerializeVersionedJsonResourceIntegrationTest { private static final Path JSON_TEST_RESULT_DIRECTORY = Paths.get("src", "test", "resources", "json-test-result-strings"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "json-database"); } @Test public void createVersionedResourceAndTestSerializations() throws IOException { - Databases.createJsonDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createJsonDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openJsonDatabase(DATABASE_PATH)) { + try (final var database = Databases.openJsonDatabase(databasePath)) { VersionedJsonDocumentCreator.create(database); try (final var manager = database.openResourceManager("resource")) { diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceAndQueryIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceAndQueryIntegrationTest.java index 3cef0ad561..92155e5bd5 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceAndQueryIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceAndQueryIntegrationTest.java @@ -1,16 +1,9 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.api.ResourceManager; @@ -25,28 +18,29 @@ import org.sirix.axis.visitor.VisitorDescendantAxis; import org.sirix.node.immutable.xdm.ImmutableElement; import org.sirix.node.immutable.xdm.ImmutableText; -public final class CreateVersionedXmlResourceAndQueryIntegrationTest { - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); +import java.nio.file.Path; +import java.nio.file.Paths; - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "xml-database"); +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class CreateVersionedXmlResourceAndQueryIntegrationTest { + + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); + + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test - public void createVersionedResourceAndQueryWithTheVisitoDescendantAxis() throws IOException { - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + public void createVersionedResourceAndQueryWithTheVisitToDescendantAxis() { + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { VersionedXmlDocumentCreator.create(database); try (final var manager = database.openResourceManager("resource"); diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceIntegrationTest.java index df6fee7723..e0f5216801 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateVersionedXmlResourceIntegrationTest.java @@ -1,41 +1,35 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertEquals; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - import org.brackit.xquery.atomic.QNm; -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + public final class CreateVersionedXmlResourceIntegrationTest { - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "json-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test public void createVersionedResourceAndCheck() { - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { VersionedXmlDocumentCreator.create(database); // Check first revision. diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateXmlDatabaseIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateXmlDatabaseIntegrationTest.java index 95334ca00c..f9c7ba689d 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateXmlDatabaseIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/CreateXmlDatabaseIntegrationTest.java @@ -1,6 +1,14 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sirix.access.DatabaseConfiguration; +import org.sirix.access.Databases; +import org.sirix.access.ResourceConfiguration; +import org.sirix.service.xml.serialize.XmlSerializer; +import org.sirix.service.xml.shredder.XmlShredder; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; @@ -11,14 +19,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sirix.access.DatabaseConfiguration; -import org.sirix.access.Databases; -import org.sirix.access.ResourceConfiguration; -import org.sirix.service.xml.serialize.XmlSerializer; -import org.sirix.service.xml.shredder.XmlShredder; +import static org.junit.Assert.assertEquals; public final class CreateXmlDatabaseIntegrationTest { @@ -26,20 +27,14 @@ public final class CreateXmlDatabaseIntegrationTest { private static final Path XML_DIRECTORY = Paths.get("src", "test", "resources", "xml"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "xml-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test @@ -47,10 +42,10 @@ public final class CreateXmlDatabaseIntegrationTest { final var pathToXmlFile = XML_DIRECTORY.resolve("orga.xml"); // Create an empty XML database. - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); // Open the database. - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { // Create a resource to store an XML-document. database.createResource(ResourceConfiguration.newBuilder("resource") .useTextCompression(false) diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/DiffXmlResourceIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/DiffXmlResourceIntegrationTest.java index 6ea5974fdf..8284fa2575 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/DiffXmlResourceIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/DiffXmlResourceIntegrationTest.java @@ -1,15 +1,10 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; +import com.google.common.collect.ImmutableSet; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.access.trx.node.HashType; @@ -17,30 +12,28 @@ import org.sirix.diff.DiffFactory; import org.sirix.diff.DiffFactory.DiffOptimized; import org.sirix.diff.DiffFactory.DiffType; -import com.google.common.collect.ImmutableSet; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; public class DiffXmlResourceIntegrationTest { - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "xml-database"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); + + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test - public void createVersionedResourceAndCheckDiffingOfRevisionOneAndThree() throws IOException { - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + public void createVersionedResourceAndCheckDiffingOfRevisionOneAndThree() { + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { VersionedXmlDocumentCreator.create(database); try (final var manager = database.openResourceManager("resource"); diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/QueryXmlResourceWithConcurrentAxisIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/QueryXmlResourceWithConcurrentAxisIntegrationTest.java index 7833e2ed1a..157c021296 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/QueryXmlResourceWithConcurrentAxisIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/QueryXmlResourceWithConcurrentAxisIntegrationTest.java @@ -1,16 +1,9 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertEquals; - -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sirix.access.DatabaseConfiguration; import org.sirix.access.Databases; import org.sirix.access.ResourceConfiguration; @@ -24,6 +17,15 @@ import org.sirix.axis.filter.FilterAxis; import org.sirix.axis.filter.xml.XdmNameFilter; import org.sirix.service.xml.shredder.XmlShredder; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * Note that this simple test shows, that the higher level XQuery-API is much more user-friendly, when chaining * axis is required. @@ -32,20 +34,14 @@ public class QueryXmlResourceWithConcurrentAxisIntegrationTest { private static final Path XML_DIRECTORY = Paths.get("src", "test", "resources", "xml"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "xml-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test @@ -53,10 +49,10 @@ public class QueryXmlResourceWithConcurrentAxisIntegrationTest { final var pathToXmlFile = XML_DIRECTORY.resolve("regions.xml"); // Create an empty XML database. - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); // Open the database. - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { // Create a resource to store an XML-document. database.createResource(ResourceConfiguration.newBuilder("resource") .useTextCompression(false) @@ -96,10 +92,10 @@ public class QueryXmlResourceWithConcurrentAxisIntegrationTest { final var resultNumber = 55; for (int i = 0; i < resultNumber; i++) { - assertEquals(true, axis.hasNext()); + assertTrue(axis.hasNext()); axis.next(); } - assertEquals(false, axis.hasNext()); + assertFalse(axis.hasNext()); } } } diff --git a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/SerializeVersionedXmlResourceIntegrationTest.java b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/SerializeVersionedXmlResourceIntegrationTest.java index 19adf49826..b94ba1e1bd 100644 --- a/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/SerializeVersionedXmlResourceIntegrationTest.java +++ b/persistence-modules/sirix/src/test/java/io/sirix/tutorial/xml/SerializeVersionedXmlResourceIntegrationTest.java @@ -1,6 +1,13 @@ package io.sirix.tutorial.xml; -import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sirix.access.DatabaseConfiguration; +import org.sirix.access.Databases; +import org.sirix.api.xml.XmlResourceManager; +import org.sirix.service.xml.serialize.XmlSerializer; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -10,39 +17,27 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sirix.access.DatabaseConfiguration; -import org.sirix.access.Databases; -import org.sirix.api.xml.XmlResourceManager; -import org.sirix.service.xml.serialize.XmlSerializer; +import static org.junit.Assert.assertEquals; public class SerializeVersionedXmlResourceIntegrationTest { private static final Path XML_TEST_RESULT_DIRECTORY = Paths.get("src", "test", "resources", "xml-test-result-strings"); - private static final String TMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); - private static final Path DATABASE_PATH = Paths.get(TMP_DIRECTORY, "sirix", "xml-database"); + private Path databasePath; @Before - public void setUp() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); - } - - @After - public void tearDown() throws Exception { - if (Files.exists(DATABASE_PATH)) - Databases.removeDatabase(DATABASE_PATH); + public void setUp() { + databasePath = Paths.get(tempDirectory.getRoot().getPath(), "sirix", "xml-database"); } @Test public void createVersionedResourceAndTestSerializations() throws IOException { - Databases.createXmlDatabase(new DatabaseConfiguration(DATABASE_PATH)); + Databases.createXmlDatabase(new DatabaseConfiguration(databasePath)); - try (final var database = Databases.openXmlDatabase(DATABASE_PATH)) { + try (final var database = Databases.openXmlDatabase(databasePath)) { VersionedXmlDocumentCreator.create(database); try (final var manager = database.openResourceManager("resource")) { diff --git a/persistence-modules/spring-boot-persistence-2/src/test/resources/logback-test.xml b/persistence-modules/spring-boot-persistence-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/config/DatasourceProxyBeanPostProcessor.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/config/DatasourceProxyBeanPostProcessor.java index c087427b65..1952a26f2f 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/config/DatasourceProxyBeanPostProcessor.java +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/config/DatasourceProxyBeanPostProcessor.java @@ -1,10 +1,7 @@ package com.baeldung.h2db.lazy_load_no_trans.config; import net.ttddyy.dsproxy.listener.DataSourceQueryCountListener; -import net.ttddyy.dsproxy.listener.logging.CommonsQueryLoggingListener; -import net.ttddyy.dsproxy.listener.logging.DefaultQueryLogEntryCreator; import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel; -import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener; import net.ttddyy.dsproxy.support.ProxyDataSource; import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; import org.aopalliance.intercept.MethodInterceptor; @@ -49,7 +46,7 @@ public class DatasourceProxyBeanPostProcessor implements BeanPostProcessor { this.dataSource = ProxyDataSourceBuilder.create(dataSource) .name("MyDS") .multiline() - .logQueryBySlf4j(SLF4JLogLevel.INFO) + .logQueryBySlf4j(SLF4JLogLevel.DEBUG) .listener(new DataSourceQueryCountListener()) .build(); } diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java index 378093cfa9..d6d7a20f55 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java @@ -2,8 +2,10 @@ package com.baeldung.h2db.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; @SpringBootApplication +@PropertySource("classpath:application-h2.properties") public class SpringBootH2Application { public static void main(String... args) { diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/CountryRepository.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/CountryRepository.java new file mode 100644 index 0000000000..d576be9098 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/CountryRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.h2db.springboot.daos; + +import com.baeldung.h2db.springboot.models.Country; +import org.springframework.data.repository.CrudRepository; + +public interface CountryRepository extends CrudRepository { +} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java deleted file mode 100644 index 35e496e910..0000000000 --- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.h2db.springboot.daos; - - - - -import com.baeldung.h2db.springboot.models.User; -import org.springframework.data.repository.CrudRepository; - -public interface UserRepository extends CrudRepository { -} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java new file mode 100644 index 0000000000..d6edab9421 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java @@ -0,0 +1,57 @@ +package com.baeldung.h2db.springboot.models; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Objects; + +@Table(name = "countries") +@Entity +public class Country { + + @Id + @GeneratedValue + private int id; + + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Country country = (Country) o; + return id == country.id && name.equals(country.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + return "Country{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java deleted file mode 100644 index fa3c01c035..0000000000 --- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.h2db.springboot.models; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; - -@Table(name = "users") -@Entity -public class User { - - @Id - @GeneratedValue - private int id; - - private String firstName; - - private String lastName; - - public User() { } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - @Override - public String toString() { - return "User{" + - "id=" + id + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - '}'; - } -} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties new file mode 100644 index 0000000000..6fb436f520 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties @@ -0,0 +1 @@ +spring.sql.init.data-locations=data-h2.sql diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties index 134cda6628..2499d7cd06 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.datasource.username=sa spring.datasource.password= spring.jpa.defer-datasource-initialization=true spring.jpa.hibernate.ddl-auto=create-drop -spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.validator.apply_to_ddl=false #spring.jpa.properties.hibernate.check_nullability=true diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-h2.sql b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-h2.sql new file mode 100644 index 0000000000..3d04b578d2 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-h2.sql @@ -0,0 +1,5 @@ +INSERT INTO countries (id, name) VALUES (1, 'USA'); +INSERT INTO countries (id, name) VALUES (2, 'France'); +INSERT INTO countries (id, name) VALUES (3, 'Brazil'); +INSERT INTO countries (id, name) VALUES (4, 'Italy'); +INSERT INTO countries (id, name) VALUES (5, 'Canada'); \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql index b8835e70cb..e4fda99437 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql @@ -1,17 +1,3 @@ -DROP TABLE IF EXISTS billionaires; - -CREATE TABLE billionaires ( - id INT AUTO_INCREMENT PRIMARY KEY, - first_name VARCHAR(250) NOT NULL, - last_name VARCHAR(250) NOT NULL, - career VARCHAR(250) DEFAULT NULL -); - -INSERT INTO billionaires (first_name, last_name, career) VALUES -('Aliko', 'Dangote', 'Billionaire Industrialist'), -('Bill', 'Gates', 'Billionaire Tech Entrepreneur'), -('Folrunsho', 'Alakija', 'Billionaire Oil Magnate'); - insert into USER values (101, 'user1', 'comment1'); insert into USER values (102, 'user2', 'comment2'); insert into USER values (103, 'user3', 'comment3'); diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/logback.xml b/persistence-modules/spring-boot-persistence-h2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/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/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java index aecc63c599..4c11ae6b0d 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java @@ -1,50 +1,39 @@ package com.baeldung; import com.baeldung.h2db.springboot.SpringBootH2Application; -import com.baeldung.h2db.springboot.daos.UserRepository; -import com.baeldung.h2db.springboot.models.User; +import com.baeldung.h2db.springboot.daos.CountryRepository; +import com.baeldung.h2db.springboot.models.Country; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import java.util.List; - -import static org.junit.Assert.*; +import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(classes = SpringBootH2Application.class) public class SpringBootH2IntegrationTest { + private static final Country AN_EXPECTED_COUNTRY = buildCountry(); + @Autowired - private UserRepository userRepository; + private CountryRepository countryRepository; @Test - public void contextLoads() { } + public void givenInitData_whenApplicationStarts_thenDataIsLoaded() { + Iterable users = countryRepository.findAll(); - @Test - public void givenUserProfile_whenAddUser_thenCreateNewUser() { - User user = new User(); - user.setFirstName("John"); - user.setLastName("Doe"); - userRepository.save(user); - List users = (List) userRepository.findAll(); - assertFalse(users.isEmpty()); + assertThat(users) + .hasSize(5) + .contains(AN_EXPECTED_COUNTRY); + } - String firstName = "Aliko"; - String lastName = "Dangote"; - User user1 = userRepository.findById(users.get(0).getId()).get(); - user1.setLastName(lastName); - user1.setFirstName(firstName); - userRepository.save(user1); - - user = userRepository.findById(user.getId()).get(); - assertEquals(user.getFirstName(), firstName); - assertEquals(user.getLastName(), lastName); - - userRepository.deleteById(user.getId()); - assertTrue( ((List) userRepository.findAll()).isEmpty()); + private static Country buildCountry() { + Country c = new Country(); + c.setId(5); + c.setName("Canada"); + return c; } } diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/resources/logback-test.xml b/persistence-modules/spring-boot-persistence-h2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/pom.xml b/persistence-modules/spring-boot-persistence-mongodb/pom.xml index 724fa38f7e..8b36474777 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/pom.xml +++ b/persistence-modules/spring-boot-persistence-mongodb/pom.xml @@ -32,8 +32,13 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo + ${embed.mongo.version} test + + 3.2.6 + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/application.properties b/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/application.properties new file mode 100644 index 0000000000..a5b5fb9804 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.mongodb.embedded.version=4.4.9 \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/logback-test.xml b/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence/README.md b/persistence-modules/spring-boot-persistence/README.md index a9fe3905c2..88526cdb89 100644 --- a/persistence-modules/spring-boot-persistence/README.md +++ b/persistence-modules/spring-boot-persistence/README.md @@ -7,5 +7,4 @@ - [Resolving “Failed to Configure a DataSource” Error](https://www.baeldung.com/spring-boot-failed-to-configure-data-source) - [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) - [Spring Boot with Hibernate](https://www.baeldung.com/spring-boot-hibernate) -- [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source) -- More articles: [[more -->]](../spring-boot-persistence-2) \ No newline at end of file +- More articles: [[more -->]](../spring-boot-persistence-2) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index deac0c2a57..58b4dd8b9e 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -37,11 +37,6 @@ org.springframework.boot spring-boot-starter-test - - org.mockito - mockito-core - test - com.h2database h2 diff --git a/persistence-modules/spring-boot-persistence/src/test/resources/dsrouting-db.sql b/persistence-modules/spring-boot-persistence/src/test/resources/dsrouting-db.sql index c9ca52907a..7449b23307 100644 --- a/persistence-modules/spring-boot-persistence/src/test/resources/dsrouting-db.sql +++ b/persistence-modules/spring-boot-persistence/src/test/resources/dsrouting-db.sql @@ -1,3 +1,5 @@ +drop table if exists client; + create table client ( id numeric, name varchar(50), diff --git a/persistence-modules/spring-data-arangodb/pom.xml b/persistence-modules/spring-data-arangodb/pom.xml index 7303316edb..e005a00ebd 100644 --- a/persistence-modules/spring-data-arangodb/pom.xml +++ b/persistence-modules/spring-data-arangodb/pom.xml @@ -21,8 +21,12 @@ com.arangodb arangodb-spring-data - 3.5.0 + ${arangodb.version} + + 3.5.0 + + \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-2/pom.xml b/persistence-modules/spring-data-cassandra-2/pom.xml index 0e09448d0f..1e6412dc17 100644 --- a/persistence-modules/spring-data-cassandra-2/pom.xml +++ b/persistence-modules/spring-data-cassandra-2/pom.xml @@ -1,72 +1,73 @@ - - 4.0.0 - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - + + 4.0.0 + org.baeldung + spring-data-cassandra-2 + 0.0.1-SNAPSHOT + spring-data-cassandra-2 + Demo project for Spring Data Cassandra - org.baeldung - spring-cassandra - 0.0.1-SNAPSHOT - spring-cassandra - Demo project for Spring Data Cassandra + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + - - - org.springframework.boot - spring-boot-starter-data-cassandra - - - org.springframework.data - spring-data-cassandra - ${org.springframework.data.version} - - - uk.org.webcompere - system-stubs-core - ${system.stubs.version} - - - org.springframework.boot - spring-boot-starter-test - test - - - org.testcontainers - testcontainers - ${testcontainers.version} - test - - - org.testcontainers - cassandra - ${testcontainers.version} - test - - - org.testcontainers - junit-jupiter - ${testcontainers.version} - test - - - uk.org.webcompere - system-stubs-jupiter - ${system.stubs.version} - test - - + + + org.springframework.boot + spring-boot-starter-data-cassandra + + + org.springframework.data + spring-data-cassandra + ${org.springframework.data.version} + + + uk.org.webcompere + system-stubs-core + ${system.stubs.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + org.testcontainers + cassandra + ${testcontainers.version} + test + + + org.testcontainers + junit-jupiter + ${testcontainers.version} + test + + + uk.org.webcompere + system-stubs-jupiter + ${system.stubs.version} + test + + - - 11 - 3.1.11 - 1.15.3 - 1.1.0 - 5.6.2 - + + 11 + 3.1.11 + 1.15.3 + 1.1.0 + 5.6.2 + - + \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedIntegrationTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java similarity index 94% rename from persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedIntegrationTest.java rename to persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java index 668f5eabd7..60f733794d 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraNestedLiveTest.java @@ -19,10 +19,11 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +// This live test needs a running Docker instance so that a Cassandra container can be created @Testcontainers @SpringBootTest -class CassandraNestedIntegrationTest { +class CassandraNestedLiveTest { private static final String KEYSPACE_NAME = "test"; @@ -47,7 +48,7 @@ class CassandraNestedIntegrationTest { } @Nested - class ApplicationContextIntegrationTest { + class ApplicationContextLiveTest { @Test void givenCassandraContainer_whenSpringContextIsBootstrapped_thenContainerIsRunningWithNoExceptions() { @@ -57,7 +58,7 @@ class CassandraNestedIntegrationTest { } @Nested - class CarRepositoryIntegrationTest { + class CarRepositoryLiveTest { @Autowired private CarRepository carRepository; diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleIntegrationTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java similarity index 82% rename from persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleIntegrationTest.java rename to persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java index fef162a1b7..02dc1f5a87 100644 --- a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/springcassandra/CassandraSimpleLiveTest.java @@ -2,26 +2,20 @@ package org.baeldung.springcassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; -import com.datastax.driver.core.utils.UUIDs; -import org.baeldung.springcassandra.model.Car; -import org.baeldung.springcassandra.repository.CarRepository; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.util.List; -import java.util.UUID; - import static org.assertj.core.api.Assertions.assertThat; +// This live test needs a running Docker instance so that a Cassandra container can be created + @Testcontainers @SpringBootTest -class CassandraSimpleIntegrationTest { +class CassandraSimpleLiveTest { private static final String KEYSPACE_NAME = "test"; diff --git a/persistence-modules/spring-data-cassandra-reactive/src/test/resources/logback-test.xml b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra/pom.xml b/persistence-modules/spring-data-cassandra/pom.xml index 8092c05a40..925031b141 100644 --- a/persistence-modules/spring-data-cassandra/pom.xml +++ b/persistence-modules/spring-data-cassandra/pom.xml @@ -49,7 +49,8 @@ ${cassandra-unit-shaded.version} test - + junit junit diff --git a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/SpringContextTest.java index 22bd5c6551..83b7b227b3 100644 --- a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/SpringContextTest.java +++ b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/SpringContextTest.java @@ -32,10 +32,10 @@ public class SpringContextTest { public static final String KEYSPACE_ACTIVATE_QUERY = "USE testKeySpace;"; public static final String DATA_TABLE_NAME = "book"; - + @Autowired private CassandraAdminOperations adminTemplate; - + @BeforeClass public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException { EmbeddedCassandraServerHelper.startEmbeddedCassandra(); @@ -47,14 +47,14 @@ public class SpringContextTest { } @Before - public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException { - adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap()); + public void createTable() { + adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<>()); } - + @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { } - + @After public void dropTable() { adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME)); diff --git a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryLiveTest.java similarity index 92% rename from persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java rename to persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryLiveTest.java index 55e968d6f2..d5758c3574 100644 --- a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/BookRepositoryLiveTest.java @@ -1,17 +1,15 @@ package com.baeldung.spring.data.cassandra.repository; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import java.io.IOException; -import java.util.HashMap; - +import com.baeldung.spring.data.cassandra.config.CassandraConfig; import com.baeldung.spring.data.cassandra.model.Book; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.collect.ImmutableSet; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.thrift.transport.TTransportException; -import com.baeldung.spring.data.cassandra.config.CassandraConfig; import org.cassandraunit.utils.EmbeddedCassandraServerHelper; import org.junit.After; import org.junit.AfterClass; @@ -25,15 +23,24 @@ import org.springframework.data.cassandra.core.CassandraAdminOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.utils.UUIDs; -import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.util.HashMap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Live test for Cassandra testing. + * + * This can be converted to IntegrationTest once cassandra-unit tests can be executed in parallel and + * multiple test servers started as part of test suite. + * + * Open cassandra-unit issue for parallel execution: https://github.com/jsevellec/cassandra-unit/issues/155 + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CassandraConfig.class) -public class BookRepositoryIntegrationTest { - private static final Log LOGGER = LogFactory.getLog(BookRepositoryIntegrationTest.class); +public class BookRepositoryLiveTest { + private static final Log LOGGER = LogFactory.getLog(BookRepositoryLiveTest.class); public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };"; @@ -47,8 +54,6 @@ public class BookRepositoryIntegrationTest { @Autowired private CassandraAdminOperations adminTemplate; - // - @BeforeClass public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException { EmbeddedCassandraServerHelper.startEmbeddedCassandra(); @@ -62,8 +67,8 @@ public class BookRepositoryIntegrationTest { } @Before - public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException { - adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap()); + public void createTable() { + adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<>()); } @Test diff --git a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateLiveTest.java similarity index 93% rename from persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java rename to persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateLiveTest.java index 90ae68ba98..bc05302d13 100644 --- a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CassandraTemplateLiveTest.java @@ -1,17 +1,13 @@ package com.baeldung.spring.data.cassandra.repository; -import static junit.framework.TestCase.assertNull; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - import com.baeldung.spring.data.cassandra.config.CassandraConfig; import com.baeldung.spring.data.cassandra.model.Book; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.querybuilder.Select; +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.collect.ImmutableSet; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -30,17 +26,28 @@ import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.querybuilder.QueryBuilder; -import com.datastax.driver.core.querybuilder.Select; -import com.datastax.driver.core.utils.UUIDs; -import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import static junit.framework.TestCase.assertNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +/** + * Live test for Cassandra testing. + * + * This can be converted to IntegrationTest once cassandra-unit tests can be executed in parallel and + * multiple test servers started as part of test suite. + * + * Open cassandra-unit issue for parallel execution: https://github.com/jsevellec/cassandra-unit/issues/155 + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CassandraConfig.class) -public class CassandraTemplateIntegrationTest { - private static final Log LOGGER = LogFactory.getLog(CassandraTemplateIntegrationTest.class); +public class CassandraTemplateLiveTest { + private static final Log LOGGER = LogFactory.getLog(CassandraTemplateLiveTest.class); public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };"; @@ -54,8 +61,6 @@ public class CassandraTemplateIntegrationTest { @Autowired private CassandraOperations cassandraTemplate; - // - @BeforeClass public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException { EmbeddedCassandraServerHelper.startEmbeddedCassandra(); @@ -69,8 +74,8 @@ public class CassandraTemplateIntegrationTest { } @Before - public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException { - adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap()); + public void createTable() { + adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<>()); } @Test @@ -111,7 +116,7 @@ public class CassandraTemplateIntegrationTest { } @Test - public void whenDeletingASelectedBook_thenNotAvailableOnRetrieval() throws InterruptedException { + public void whenDeletingASelectedBook_thenNotAvailableOnRetrieval() { final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "OReilly Media", ImmutableSet.of("Computer", "Software")); cassandraTemplate.insert(javaBook); cassandraTemplate.delete(javaBook); diff --git a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesLiveTest.java similarity index 90% rename from persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java rename to persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesLiveTest.java index f948218807..e1c67a1724 100644 --- a/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra/src/test/java/com/baeldung/spring/data/cassandra/repository/CqlQueriesLiveTest.java @@ -1,19 +1,16 @@ package com.baeldung.spring.data.cassandra.repository; -import static junit.framework.TestCase.assertEquals; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.thrift.transport.TTransportException; import com.baeldung.spring.data.cassandra.config.CassandraConfig; import com.baeldung.spring.data.cassandra.model.Book; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.querybuilder.Insert; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.querybuilder.Select; +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.collect.ImmutableSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.cassandraunit.utils.EmbeddedCassandraServerHelper; import org.junit.After; import org.junit.AfterClass; @@ -28,18 +25,25 @@ import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.querybuilder.Insert; -import com.datastax.driver.core.querybuilder.QueryBuilder; -import com.datastax.driver.core.querybuilder.Select; -import com.datastax.driver.core.utils.UUIDs; -import com.google.common.collect.ImmutableSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; +import static junit.framework.TestCase.assertEquals; + +/** + * Live test for Cassandra testing. + * + * This can be converted to IntegrationTest once cassandra-unit tests can be executed in parallel and + * multiple test servers started as part of test suite. + * + * Open cassandra-unit issue for parallel execution: https://github.com/jsevellec/cassandra-unit/issues/155 + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CassandraConfig.class) -public class CqlQueriesIntegrationTest { - private static final Log LOGGER = LogFactory.getLog(CqlQueriesIntegrationTest.class); +public class CqlQueriesLiveTest { + private static final Log LOGGER = LogFactory.getLog(CqlQueriesLiveTest.class); public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };"; @@ -53,10 +57,8 @@ public class CqlQueriesIntegrationTest { @Autowired private CassandraOperations cassandraTemplate; - // - @BeforeClass - public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException { + public static void startCassandraEmbedded() throws Exception { EmbeddedCassandraServerHelper.startEmbeddedCassandra(25000); final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build(); LOGGER.info("Server Started at 127.0.0.1:9142... "); @@ -68,8 +70,8 @@ public class CqlQueriesIntegrationTest { } @Before - public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException { - adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap()); + public void createTable() { + adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<>()); } @Test diff --git a/persistence-modules/spring-data-eclipselink/pom.xml b/persistence-modules/spring-data-eclipselink/pom.xml index a344d64864..561d144fe3 100644 --- a/persistence-modules/spring-data-eclipselink/pom.xml +++ b/persistence-modules/spring-data-eclipselink/pom.xml @@ -66,6 +66,7 @@ 1.5.9.RELEASE 2.7.0 + 1.4.197 \ No newline at end of file diff --git a/persistence-modules/spring-data-jdbc/README.md b/persistence-modules/spring-data-jdbc/README.md index 0e54d0ba88..b9ff9417a9 100644 --- a/persistence-modules/spring-data-jdbc/README.md +++ b/persistence-modules/spring-data-jdbc/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: +- [Configure and Use Multiple DataSources in Spring Boot](https://www.baeldung.com/spring-boot-configure-multiple-datasources) - [Introduction to Spring Data JDBC](https://www.baeldung.com/spring-data-jdbc-intro) diff --git a/persistence-modules/spring-data-jdbc/pom.xml b/persistence-modules/spring-data-jdbc/pom.xml index 2b4c6d21aa..168b171337 100644 --- a/persistence-modules/spring-data-jdbc/pom.xml +++ b/persistence-modules/spring-data-jdbc/pom.xml @@ -21,11 +21,19 @@ org.springframework.boot spring-boot-starter-data-jdbc + + org.springframework.boot + spring-boot-starter-data-jpa + com.h2database h2 runtime + + org.springframework.boot + spring-boot-starter-test + - \ No newline at end of file + diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/Application.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/Application.java index 8fff82de32..a808a3daea 100644 --- a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/Application.java +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/Application.java @@ -1,17 +1,16 @@ package com.baeldung.springdatajdbcintro; -import java.util.Optional; - +import ch.qos.logback.classic.Logger; +import com.baeldung.springdatajdbcintro.entity.Person; +import com.baeldung.springdatajdbcintro.repository.PersonRepository; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.core.env.AbstractEnvironment; -import com.baeldung.springdatajdbcintro.entity.Person; -import com.baeldung.springdatajdbcintro.repository.PersonRepository; - -import ch.qos.logback.classic.Logger; +import java.util.Optional; @SpringBootApplication public class Application implements CommandLineRunner { @@ -24,6 +23,7 @@ public class Application implements CommandLineRunner { private DatabaseSeeder dbSeeder; public static void main(String[] args) { + System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "jdbcintro"); SpringApplication.run(Application.class, args); } diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/entity/Person.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/entity/Person.java index 7c4c1eec73..ac2c329e08 100644 --- a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/entity/Person.java +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/entity/Person.java @@ -1,7 +1,9 @@ package com.baeldung.springdatajdbcintro.entity; import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Table; +@Table public class Person { @Id diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/repository/PersonRepository.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/repository/PersonRepository.java index b2f026fa0c..ceb7a968a4 100644 --- a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/repository/PersonRepository.java +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springdatajdbcintro/repository/PersonRepository.java @@ -3,6 +3,7 @@ package com.baeldung.springdatajdbcintro.repository; import com.baeldung.springdatajdbcintro.entity.Person; import org.springframework.data.jdbc.repository.query.Modifying; import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/Application.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/Application.java new file mode 100644 index 0000000000..a08949585c --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/Application.java @@ -0,0 +1,15 @@ +package com.baeldung.springmultipledatasources; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.core.env.AbstractEnvironment; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "multipledatasources"); + SpringApplication.run(Application.class, args); + } + +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/Todo.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/Todo.java new file mode 100644 index 0000000000..56f513027b --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/Todo.java @@ -0,0 +1,48 @@ +package com.baeldung.springmultipledatasources.todos; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Todo { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String title; + private boolean completed; + + public Todo() { + } + + public Todo(String title) { + this.title = title; + } + + 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 boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoDatasourceConfiguration.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoDatasourceConfiguration.java new file mode 100644 index 0000000000..b6a16eb7e4 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoDatasourceConfiguration.java @@ -0,0 +1,28 @@ +package com.baeldung.springmultipledatasources.todos; + +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import javax.sql.DataSource; + +@Configuration +public class TodoDatasourceConfiguration { + + @Bean + @ConfigurationProperties("spring.datasource.todos") + public DataSourceProperties todosDataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + @Primary + public DataSource todosDataSource() { + return todosDataSourceProperties() + .initializeDataSourceBuilder() + .build(); + } + +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoJpaConfiguration.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoJpaConfiguration.java new file mode 100644 index 0000000000..e1c4e1c9be --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoJpaConfiguration.java @@ -0,0 +1,40 @@ +package com.baeldung.springmultipledatasources.todos; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + basePackageClasses = Todo.class, + entityManagerFactoryRef = "todosEntityManagerFactory", + transactionManagerRef = "todosTransactionManager" +) +public class TodoJpaConfiguration { + + @Bean + public LocalContainerEntityManagerFactoryBean todosEntityManagerFactory( + @Qualifier("todosDataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder) { + return builder + .dataSource(dataSource) + .packages(Todo.class) + .build(); + } + + @Bean + public PlatformTransactionManager todosTransactionManager( + @Qualifier("todosEntityManagerFactory") LocalContainerEntityManagerFactoryBean todosEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(todosEntityManagerFactory.getObject())); + } +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoRepository.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoRepository.java new file mode 100644 index 0000000000..ebdd59551b --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/todos/TodoRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.springmultipledatasources.todos; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TodoRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/Topic.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/Topic.java new file mode 100644 index 0000000000..390300ff1a --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/Topic.java @@ -0,0 +1,39 @@ +package com.baeldung.springmultipledatasources.topics; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Topic { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String title; + + public Topic() { + } + + public Topic(String title) { + this.title = title; + } + + 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; + } + +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicDatasourceConfiguration.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicDatasourceConfiguration.java new file mode 100644 index 0000000000..38daa13d7d --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicDatasourceConfiguration.java @@ -0,0 +1,26 @@ +package com.baeldung.springmultipledatasources.topics; + +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class TopicDatasourceConfiguration { + + @Bean + @ConfigurationProperties("spring.datasource.topics") + public DataSourceProperties topicsDataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + public DataSource topicsDataSource() { + return topicsDataSourceProperties() + .initializeDataSourceBuilder() + .build(); + } + +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicJpaConfiguration.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicJpaConfiguration.java new file mode 100644 index 0000000000..a7daf54c07 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicJpaConfiguration.java @@ -0,0 +1,41 @@ +package com.baeldung.springmultipledatasources.topics; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + basePackageClasses = Topic.class, + entityManagerFactoryRef = "topicsEntityManagerFactory", + transactionManagerRef = "topicsTransactionManager" +) +public class TopicJpaConfiguration { + + @Bean + public LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory( + @Qualifier("topicsDataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder + ) { + return builder + .dataSource(dataSource) + .packages(Topic.class) + .build(); + } + + @Bean + public PlatformTransactionManager topicsTransactionManager( + @Qualifier("topicsEntityManagerFactory") LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(topicsEntityManagerFactory.getObject())); + } +} diff --git a/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicRepository.java b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicRepository.java new file mode 100644 index 0000000000..5aebc3fe87 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/java/com/baeldung/springmultipledatasources/topics/TopicRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.springmultipledatasources.topics; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TopicRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-data-jdbc/src/main/resources/application-jdbcintro.properties b/persistence-modules/spring-data-jdbc/src/main/resources/application-jdbcintro.properties new file mode 100644 index 0000000000..4980c71be4 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/resources/application-jdbcintro.properties @@ -0,0 +1,6 @@ +#H2 DB +spring.jpa.hibernate.ddl-auto=none +spring.datasource.url=jdbc:h2:mem:persondb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=test diff --git a/persistence-modules/spring-data-jdbc/src/main/resources/application-multipledatasources.properties b/persistence-modules/spring-data-jdbc/src/main/resources/application-multipledatasources.properties new file mode 100644 index 0000000000..0f2b643498 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/main/resources/application-multipledatasources.properties @@ -0,0 +1,9 @@ +spring.jpa.hibernate.ddl-auto=update +spring.datasource.todos.url=jdbc:h2:mem:todos +spring.datasource.todos.username=sa +spring.datasource.todos.password=null +spring.datasource.todos.driverClassName=org.h2.Driver +spring.datasource.topics.url=jdbc:h2:mem:topics +spring.datasource.topics.username=sa +spring.datasource.topics.password=null +spring.datasource.topics.driverClassName=org.h2.Driver diff --git a/persistence-modules/spring-data-jdbc/src/main/resources/application.properties b/persistence-modules/spring-data-jdbc/src/main/resources/application.properties index 45099222fc..2a0c259c00 100644 --- a/persistence-modules/spring-data-jdbc/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jdbc/src/main/resources/application.properties @@ -1,8 +1,3 @@ #H2 DB -spring.jpa.hibernate.ddl-auto=none spring.h2.console.enabled=true -spring.datasource.url=jdbc:h2:mem:persondb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=test -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect diff --git a/persistence-modules/spring-data-jdbc/src/test/java/com/baeldung/springmultipledatasources/MultipleDatasourcesIntegrationTest.java b/persistence-modules/spring-data-jdbc/src/test/java/com/baeldung/springmultipledatasources/MultipleDatasourcesIntegrationTest.java new file mode 100644 index 0000000000..4d401396a2 --- /dev/null +++ b/persistence-modules/spring-data-jdbc/src/test/java/com/baeldung/springmultipledatasources/MultipleDatasourcesIntegrationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.springmultipledatasources; + +import com.baeldung.springmultipledatasources.todos.Todo; +import com.baeldung.springmultipledatasources.todos.TodoRepository; +import com.baeldung.springmultipledatasources.topics.Topic; +import com.baeldung.springmultipledatasources.topics.TopicRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@ActiveProfiles("multipledatasources") +@DataJpaTest // no test database! +class MultipleDatasourcesIntegrationTest { + + @Autowired + TodoRepository todoRepo; + @Autowired + TopicRepository topicRepo; + + @Test + void shouldSaveTodoToTodoDB() { + Todo todo = new Todo("test"); + Todo saved =todoRepo.save(todo); + Optional result= todoRepo.findById(saved.getId()); + assertThat(result).isPresent(); + } + + @Test + void shouldSaveTopicToTopicDB() { + Topic todo = new Topic("test"); + Topic saved =topicRepo.save(todo); + Optional result= topicRepo.findById(saved.getId()); + assertThat(result).isPresent(); + } + +} diff --git a/persistence-modules/spring-data-jpa-annotations/pom.xml b/persistence-modules/spring-data-jpa-annotations/pom.xml index 113d6e5dc6..0bbaf186c2 100644 --- a/persistence-modules/spring-data-jpa-annotations/pom.xml +++ b/persistence-modules/spring-data-jpa-annotations/pom.xml @@ -67,7 +67,6 @@ com.baeldung.boot.Application 1.10.6 42.2.5 - 21.0 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java b/persistence-modules/spring-data-jpa-annotations/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java index ac607063b2..5481d4644d 100644 --- a/persistence-modules/spring-data-jpa-annotations/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-annotations/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java @@ -3,7 +3,7 @@ package com.baeldung.boot.ddd.event; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -51,7 +51,7 @@ class AggregateEventsIntegrationTest { .domainOperation(); // then - verifyZeroInteractions(eventHandler); + verifyNoInteractions(eventHandler); } @BeforeEach diff --git a/persistence-modules/spring-data-jpa-crud-2/README.md b/persistence-modules/spring-data-jpa-crud-2/README.md new file mode 100644 index 0000000000..c912e1d5aa --- /dev/null +++ b/persistence-modules/spring-data-jpa-crud-2/README.md @@ -0,0 +1,16 @@ +## Spring Data JPA - CRUD + +This module contains articles about CRUD operations in Spring Data JPA + +### Relevant Articles: +- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) +- More articles: [[<--prev]](/persistence-modules/spring-data-jpa-crud) + +### Eclipse Config +After importing the project into Eclipse, you may see the following error: +"No persistence xml file found in project" + +This can be ignored: +- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" +Or: +- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator diff --git a/patterns/simplehexagonalexample/pom.xml b/persistence-modules/spring-data-jpa-crud-2/pom.xml similarity index 53% rename from patterns/simplehexagonalexample/pom.xml rename to persistence-modules/spring-data-jpa-crud-2/pom.xml index 31e829b7dc..ff90d0ed8b 100644 --- a/patterns/simplehexagonalexample/pom.xml +++ b/persistence-modules/spring-data-jpa-crud-2/pom.xml @@ -1,10 +1,10 @@ + + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 1.0.0-SNAPSHOT - simple-hexagonal-example - simple-hexagonal-example + spring-data-jpa-crud-2 + spring-data-jpa-crud-2 com.baeldung @@ -14,19 +14,19 @@ + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-web + + com.h2database + h2 + runtime + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/AccountApplication.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/AccountApplication.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/AccountApplication.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/AccountApplication.java diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/HibernateUtil.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/HibernateUtil.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/HibernateUtil.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/HibernateUtil.java diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/model/Account.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/Account.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/model/Account.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/Account.java diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/model/AccountSetting.java diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountRepository.java diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java b/persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java rename to persistence-modules/spring-data-jpa-crud-2/src/main/java/com/baeldung/schemageneration/repository/AccountSettingRepository.java diff --git a/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-crud-2/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java similarity index 100% rename from persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-crud-2/src/test/java/com/baeldung/schemageneration/AccountRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa-crud/README.md b/persistence-modules/spring-data-jpa-crud/README.md index 81559bb773..145153b953 100644 --- a/persistence-modules/spring-data-jpa-crud/README.md +++ b/persistence-modules/spring-data-jpa-crud/README.md @@ -9,8 +9,8 @@ This module contains articles about CRUD operations in Spring Data JPA - [Spring Data JPA Batch Inserts](https://www.baeldung.com/spring-data-jpa-batch-inserts) - [Batch Insert/Update with Hibernate/JPA](https://www.baeldung.com/jpa-hibernate-batch-insert-update) - [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush) -- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) - [How to Implement a Soft Delete with Spring JPA](https://www.baeldung.com/spring-jpa-soft-delete) +- More articles: [[next-->]](/persistence-modules/spring-data-jpa-crud-2) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-jpa-crud/pom.xml b/persistence-modules/spring-data-jpa-crud/pom.xml index 139632a42a..0889cfca2a 100644 --- a/persistence-modules/spring-data-jpa-crud/pom.xml +++ b/persistence-modules/spring-data-jpa-crud/pom.xml @@ -58,7 +58,6 @@ 1.4.1 - 21.0 1.12.2 diff --git a/persistence-modules/spring-data-jpa-enterprise-2/README.md b/persistence-modules/spring-data-jpa-enterprise-2/README.md new file mode 100644 index 0000000000..9bb08cc497 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise-2/README.md @@ -0,0 +1,18 @@ +## Spring Data JPA - Enterprise + +This module contains articles about Spring Data JPA used in enterprise applications such as transactions, sessions, naming conventions and more + +### Relevant Articles: + +- [Spring JPA – Multiple Databases](https://www.baeldung.com/spring-data-jpa-multiple-databases) +- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) + +### Eclipse Config +After importing the project into Eclipse, you may see the following error: +"No persistence xml file found in project" + +This can be ignored: +- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" +Or: +- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator + diff --git a/persistence-modules/spring-data-jpa-enterprise-2/pom.xml b/persistence-modules/spring-data-jpa-enterprise-2/pom.xml new file mode 100644 index 0000000000..f35ee378d1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise-2/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + spring-data-jpa-enterprise-2 + spring-data-jpa-enterprise-2 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + + + com.google.guava + guava + ${guava.version} + + + + \ No newline at end of file diff --git a/guest/webservices/spring-rest-service/src/main/java/com/stackify/Application.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/Application.java similarity index 90% rename from guest/webservices/spring-rest-service/src/main/java/com/stackify/Application.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/Application.java index b45ed8094f..37dbe7dab8 100644 --- a/guest/webservices/spring-rest-service/src/main/java/com/stackify/Application.java +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/Application.java @@ -1,12 +1,13 @@ -package com.stackify; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { - + public static void main(String[] args) { SpringApplication.run(Application.class, args); } + } diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java similarity index 97% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java index a6f8f0829f..bc7ab57b06 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java @@ -8,7 +8,6 @@ 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; diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java similarity index 97% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java index e04a1621b2..8080885b37 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java @@ -8,7 +8,6 @@ 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; diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java old mode 100755 new mode 100644 similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/product/Product.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/product/Product.java old mode 100755 new mode 100644 similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/product/Product.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/product/Product.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/user/Possession.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/user/Possession.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/user/Possession.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/user/Possession.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/user/User.java b/persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/user/User.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/java/com/baeldung/multipledb/model/user/User.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/java/com/baeldung/multipledb/model/user/User.java diff --git a/persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/application.properties new file mode 100644 index 0000000000..0ca1872207 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/application.properties @@ -0,0 +1,15 @@ + +spring.datasource.url=jdbc:h2:mem:baeldung + +# JPA-Schema-Generation +# Use below configuration to generate database schema create commands based on the entity models +# and export them into the create.sql file +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata +#spring.jpa.properties.hibernate.format_sql=true + +spring.jpa.show-sql=false + +#hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.properties.hibernate.id.new_generator_mappings=false \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/persistence-multiple-db-boot.properties b/persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/persistence-multiple-db-boot.properties similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/resources/persistence-multiple-db-boot.properties rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/persistence-multiple-db-boot.properties diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/persistence-multiple-db.properties b/persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/persistence-multiple-db.properties similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/main/resources/persistence-multiple-db.properties rename to persistence-modules/spring-data-jpa-enterprise-2/src/main/resources/persistence-multiple-db.properties diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java b/persistence-modules/spring-data-jpa-enterprise-2/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java similarity index 100% rename from persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-enterprise-2/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-enterprise-2/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java index 9bfba61a3b..831790af95 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java @@ -18,12 +18,10 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; -import com.baeldung.multipledb.PersistenceProductConfiguration; import com.baeldung.multipledb.dao.product.ProductRepository; import com.baeldung.multipledb.model.product.Product; diff --git a/persistence-modules/spring-data-jpa-enterprise-2/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-enterprise-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..1595326253 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise-2/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-enterprise/README.md b/persistence-modules/spring-data-jpa-enterprise/README.md index 42fbecc880..ca89bd54e7 100644 --- a/persistence-modules/spring-data-jpa-enterprise/README.md +++ b/persistence-modules/spring-data-jpa-enterprise/README.md @@ -4,9 +4,7 @@ This module contains articles about Spring Data JPA used in enterprise applicati ### Relevant Articles: -- [Spring JPA – Multiple Databases](https://www.baeldung.com/spring-data-jpa-multiple-databases) - [Spring Data Java 8 Support](https://www.baeldung.com/spring-data-java-8) -- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) - [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) - [A Guide to Spring’s Open Session In View](https://www.baeldung.com/spring-open-session-in-view) - [Working with Lazy Element Collections in JPA](https://www.baeldung.com/java-jpa-lazy-collections) diff --git a/persistence-modules/spring-data-jpa-enterprise/pom.xml b/persistence-modules/spring-data-jpa-enterprise/pom.xml index a76bcb8b0a..587261dccc 100644 --- a/persistence-modules/spring-data-jpa-enterprise/pom.xml +++ b/persistence-modules/spring-data-jpa-enterprise/pom.xml @@ -87,7 +87,6 @@ 1.3.1.Final - 21.0 1.12.2 diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties index 32d3e640f9..0ca1872207 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties @@ -9,7 +9,7 @@ spring.datasource.url=jdbc:h2:mem:baeldung #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata #spring.jpa.properties.hibernate.format_sql=true -spring.jpa.show-sql=true +spring.jpa.show-sql=false #hibernate.dialect=org.hibernate.dialect.H2Dialect spring.jpa.properties.hibernate.id.new_generator_mappings=false \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringContextTest.java index eaccf4acba..0c735d3599 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringContextTest.java +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringContextTest.java @@ -3,6 +3,7 @@ package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.boot.Application; diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java index f3697bf39f..ecaa83f3f3 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java @@ -8,14 +8,10 @@ import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.boot.Application; import com.baeldung.boot.config.PersistenceConfiguration; -import com.baeldung.multipledb.PersistenceProductConfiguration; -import com.baeldung.multipledb.PersistenceUserConfiguration; @RunWith(SpringRunner.class) @DataJpaTest(excludeAutoConfiguration = { - PersistenceConfiguration.class, - PersistenceUserConfiguration.class, - PersistenceProductConfiguration.class }) + PersistenceConfiguration.class }) @ContextConfiguration(classes = Application.class) public class SpringJpaContextIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java index 874e18c4ad..4a70d409df 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java @@ -7,6 +7,7 @@ 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.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.partialupdate.model.Customer; diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-enterprise/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..1595326253 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-filtering/pom.xml b/persistence-modules/spring-data-jpa-filtering/pom.xml index 038fd24723..9c10f4a997 100644 --- a/persistence-modules/spring-data-jpa-filtering/pom.xml +++ b/persistence-modules/spring-data-jpa-filtering/pom.xml @@ -67,7 +67,7 @@ com.baeldung.boot.Application 1.10.6 42.2.5 - 21.0 + 2.6.1 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/README.md b/persistence-modules/spring-data-jpa-query-2/README.md index 36875c899c..8005bc0e19 100644 --- a/persistence-modules/spring-data-jpa-query-2/README.md +++ b/persistence-modules/spring-data-jpa-query-2/README.md @@ -1,18 +1,17 @@ ## Spring Data JPA - Query -This module contains articles about querying data using Spring Data JPA +This module contains articles about querying data using Spring Data JPA . + +### Relevant Articles: -### Relevant Articles: - [Spring Data JPA @Query](https://www.baeldung.com/spring-data-jpa-query) - [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries) -- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) - [Hibernate Pagination](https://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](https://www.baeldung.com/hibernate-sort) - [Stored Procedures with Hibernate](https://www.baeldung.com/stored-procedures-with-hibernate-tutorial) - [Eager/Lazy Loading In Hibernate](https://www.baeldung.com/hibernate-lazy-eager-loading) - [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) - -- More articles: [[<-- prev]](../spring-data-jpa-query) +- More articles: [[<-- prev]](../spring-data-jpa-query)[[more -->]](../spring-data-jpa-query-3) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-jpa-query-2/pom.xml b/persistence-modules/spring-data-jpa-query-2/pom.xml index 96585d9325..c74c35c37b 100644 --- a/persistence-modules/spring-data-jpa-query-2/pom.xml +++ b/persistence-modules/spring-data-jpa-query-2/pom.xml @@ -30,10 +30,6 @@ com.fasterxml.jackson.core jackson-databind - - org.hibernate - hibernate-envers - javax.transaction jta @@ -56,12 +52,10 @@ org.hibernate hibernate-core - ${hibernate.version} org.hibernate hibernate-envers - ${hibernate.version} org.springframework @@ -83,9 +77,6 @@ 9.0.0.M26 1.1 - 21.0 - - 5.2.10.Final \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java index c7f05254cc..0ceb2d5626 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java @@ -1,8 +1,14 @@ package com.baeldung.persistence.model; -import java.io.Serializable; -import java.util.Date; -import java.util.Set; +import com.google.common.collect.Sets; +import org.hibernate.annotations.OrderBy; +import org.hibernate.envers.Audited; +import org.jboss.logging.Logger; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -17,17 +23,9 @@ import javax.persistence.OneToMany; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; - -import org.hibernate.annotations.OrderBy; -import org.hibernate.envers.Audited; -import org.jboss.logging.Logger; -import org.springframework.data.annotation.CreatedBy; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedBy; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import com.google.common.collect.Sets; +import java.io.Serializable; +import java.util.Date; +import java.util.Set; @Entity @NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b") @@ -35,11 +33,11 @@ import com.google.common.collect.Sets; @EntityListeners(AuditingEntityListener.class) public class Bar implements Serializable { - private static Logger logger = Logger.getLogger(Bar.class); + private static final Logger LOGGER = Logger.getLogger(Bar.class); public enum OPERATION { INSERT, UPDATE, DELETE; - private String value; + private final String value; OPERATION() { value = toString(); @@ -70,7 +68,7 @@ public class Bar implements Serializable { private String name; @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @OrderBy(clause = "NAME DESC") + @OrderBy(clause = "name DESC") // @NotAudited private Set fooSet = Sets.newHashSet(); @@ -102,7 +100,6 @@ public class Bar implements Serializable { public Bar(final String name) { super(); - this.name = name; } @@ -202,35 +199,31 @@ public class Bar implements Serializable { return false; final Bar other = (Bar) obj; if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; + return other.name == null; + } else + return name.equals(other.name); } @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Bar [name=").append(name).append("]"); - return builder.toString(); + return "Bar [name=" + name + "]"; } @PrePersist public void onPrePersist() { - logger.info("@PrePersist"); + LOGGER.info("@PrePersist"); audit(OPERATION.INSERT); } @PreUpdate public void onPreUpdate() { - logger.info("@PreUpdate"); + LOGGER.info("@PreUpdate"); audit(OPERATION.UPDATE); } @PreRemove public void onPreRemove() { - logger.info("@PreRemove"); + LOGGER.info("@PreRemove"); audit(OPERATION.DELETE); } diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java index d36a1e58cf..eec15c5e56 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java @@ -16,7 +16,10 @@ import javax.persistence.NamedNativeQuery; import org.hibernate.envers.Audited; -@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) }) +@NamedNativeQueries({ + @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), + @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) +}) @Entity @Audited // @Proxy(lazy = false) @@ -89,17 +92,13 @@ public class Foo implements Serializable { return false; final Foo other = (Foo) obj; if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; + return other.name == null; + } else + return name.equals(other.name); } @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Foo [name=").append(name).append("]"); - return builder.toString(); + return "Foo [name=" + name + "]"; } } diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java index 444324dafc..09d44956b3 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java @@ -1,17 +1,14 @@ package com.baeldung.persistence.audit; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.List; - +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IBarAuditableService; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.spring.config.PersistenceTestConfig; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.After; -import org.junit.AfterClass; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; @@ -23,28 +20,17 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import com.baeldung.persistence.model.Bar; -import com.baeldung.persistence.model.Foo; -import com.baeldung.persistence.service.IBarAuditableService; -import com.baeldung.persistence.service.IFooAuditableService; -import com.baeldung.spring.config.PersistenceTestConfig; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class EnversFooBarAuditIntegrationTest { - private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditIntegrationTest.class); - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - logger.info("setUpBeforeClass()"); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - logger.info("tearDownAfterClass()"); - } + private static final Logger LOGGER = LoggerFactory.getLogger(EnversFooBarAuditIntegrationTest.class); @Autowired @Qualifier("fooHibernateAuditableService") @@ -60,15 +46,15 @@ public class EnversFooBarAuditIntegrationTest { private Session session; @Before - public void setUp() throws Exception { - logger.info("setUp()"); + public void setUp() { + LOGGER.info("setUp()"); makeRevisions(); session = sessionFactory.openSession(); } @After - public void tearDown() throws Exception { - logger.info("tearDown()"); + public void tearDown() { + LOGGER.info("tearDown()"); session.close(); } @@ -97,14 +83,12 @@ public class EnversFooBarAuditIntegrationTest { // REV #3: update BAR private void rev3(final Bar bar) { - bar.setName("BAR1"); barService.update(bar); } // REV #4: insert FOO3 & update BAR private void rev4(final Bar bar) { - final Foo foo3 = new Foo("FOO3"); foo3.setBar(bar); fooService.create(foo3); diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java index da840dc027..a7763bb0f8 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java @@ -10,8 +10,13 @@ import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.google.common.collect.Lists; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class FooFixtures { + + private static final Logger LOGGER = LoggerFactory.getLogger(FooFixtures.class); + private SessionFactory sessionFactory; public FooFixtures(final SessionFactory sessionFactory) { @@ -36,8 +41,9 @@ public class FooFixtures { foo.setBar(bar); session.save(foo); final Foo foo2 = new Foo(null); - if (i % 2 == 0) + if (i % 2 == 0) { foo2.setName("LuckyFoo" + (i + 120)); + } foo2.setBar(bar); session.save(foo2); bar.getFooSet().add(foo); @@ -47,15 +53,16 @@ public class FooFixtures { tx.commit(); session.flush(); } catch (final HibernateException he) { - if (tx != null) + if (tx != null) { tx.rollback(); - System.out.println("Not able to open session"); - he.printStackTrace(); + } + LOGGER.error("Not able to open session", he); } catch (final Exception e) { - e.printStackTrace(); + LOGGER.error(e.getLocalizedMessage(), e); } finally { - if (session != null) + if (session != null) { session.close(); + } } } @@ -86,15 +93,16 @@ public class FooFixtures { tx.commit(); session.flush(); } catch (final HibernateException he) { - if (tx != null) + if (tx != null) { tx.rollback(); - System.out.println("Not able to open session"); - he.printStackTrace(); + } + LOGGER.error("Not able to open session", he); } catch (final Exception e) { - e.printStackTrace(); + LOGGER.error(e.getLocalizedMessage(), e); } finally { - if (session != null) + if (session != null) { session.close(); + } } } diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java index 8173088af0..6078eb3af0 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java @@ -15,6 +15,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -29,6 +31,8 @@ import com.baeldung.spring.config.PersistenceTestConfig; @SuppressWarnings("unchecked") public class FooSortingPersistenceIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(FooSortingPersistenceIntegrationTest.class); + @Autowired private SessionFactory sessionFactory; @@ -56,7 +60,7 @@ public class FooSortingPersistenceIntegrationTest { final Query query = session.createQuery(hql); final List fooList = query.list(); for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + LOGGER.debug("Name: {} , Id: {}", foo.getName(), foo.getId()); } } @@ -68,7 +72,7 @@ public class FooSortingPersistenceIntegrationTest { assertNull(fooList.get(fooList.toArray().length - 1).getName()); for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId()); } } @@ -79,7 +83,7 @@ public class FooSortingPersistenceIntegrationTest { final List fooList = query.list(); assertNull(fooList.get(0).getName()); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); + LOGGER.debug("Name: {}", foo.getName()); } } @@ -90,7 +94,7 @@ public class FooSortingPersistenceIntegrationTest { final Query query = session.createQuery(hql); final List fooList = query.list(); for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId()); } } @@ -100,7 +104,7 @@ public class FooSortingPersistenceIntegrationTest { final Query query = session.createQuery(hql); final List fooList = query.list(); for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId()); } } @@ -110,7 +114,7 @@ public class FooSortingPersistenceIntegrationTest { final Query query = session.createQuery(hql); final List fooList = query.list(); for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId()); } } @@ -120,7 +124,7 @@ public class FooSortingPersistenceIntegrationTest { criteria.addOrder(Order.asc("id")); final List fooList = criteria.list(); for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName()); } } @@ -131,7 +135,7 @@ public class FooSortingPersistenceIntegrationTest { criteria.addOrder(Order.asc("id")); final List fooList = criteria.list(); for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName()); } } @@ -142,7 +146,7 @@ public class FooSortingPersistenceIntegrationTest { final List fooList = criteria.list(); assertNull(fooList.get(fooList.toArray().length - 1).getName()); for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName()); } } @@ -153,7 +157,7 @@ public class FooSortingPersistenceIntegrationTest { final List fooList = criteria.list(); assertNull(fooList.get(0).getName()); for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName()); } } @@ -164,9 +168,9 @@ public class FooSortingPersistenceIntegrationTest { final List barList = query.list(); for (final Bar bar : barList) { final Set fooSet = bar.getFooSet(); - System.out.println("Bar Id:" + bar.getId()); + LOGGER.debug("Bar Id:{}", bar.getId()); for (final Foo foo : fooSet) { - System.out.println("FooName:" + foo.getName()); + LOGGER.debug("FooName:{}", foo.getName()); } } } diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java index 5a73e39ca2..8c766954ff 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java @@ -1,7 +1,10 @@ package com.baeldung.persistence.service; +import com.baeldung.persistence.hibernate.FooSortingPersistenceIntegrationTest; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.ContextConfiguration; @@ -16,6 +19,8 @@ import com.baeldung.spring.config.PersistenceTestConfig; @ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class) public class ParentServicePersistenceIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ParentServicePersistenceIntegrationTest.class); + @Autowired private IParentService service; @@ -37,11 +42,11 @@ public class ParentServicePersistenceIntegrationTest { final Parent parentEntity = new Parent(childEntity); service.create(parentEntity); - System.out.println("Child = " + childService.findOne(childEntity.getId())); - System.out.println("Child - parent = " + childService.findOne(childEntity.getId()).getParent()); + LOGGER.debug("Child = {}", childService.findOne(childEntity.getId())); + LOGGER.debug("Child - parent = {}", childService.findOne(childEntity.getId()).getParent()); - System.out.println("Parent = " + service.findOne(parentEntity.getId())); - System.out.println("Parent - child = " + service.findOne(parentEntity.getId()).getChild()); + LOGGER.debug("Parent = {}", service.findOne(parentEntity.getId())); + LOGGER.debug("Parent - child = {}", service.findOne(parentEntity.getId()).getChild()); } @Test(expected = DataIntegrityViolationException.class) diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java index 34301741fe..c8f14c5563 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java @@ -166,7 +166,7 @@ public class PersistenceTestConfig { hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - hibernateProperties.setProperty("hibernate.show_sql", "true"); + hibernateProperties.setProperty("hibernate.show_sql", "false"); // hibernateProperties.setProperty("hibernate.format_sql", "true"); // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java index a9ab13feed..19760f2bfe 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @RunWith(SpringRunner.class) -@DataJpaTest(properties = "spring.sql.init.data-locations=classpath:insert_users.sql") +@DataJpaTest(properties = "spring.sql.init.data-locations=classpath:insert_users.sql", showSql = false) public class UserRepositoryIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml index 55a3aeb51c..4d3ff2ae63 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml +++ b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml @@ -11,7 +11,7 @@ org.hibernate.dialect.H2Dialect update - true + false diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml index 8fcf578660..8a2bf593cb 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml +++ b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml @@ -11,7 +11,7 @@ org.hibernate.dialect.H2Dialect update - true + false diff --git a/persistence-modules/spring-data-jpa-query-3/README.md b/persistence-modules/spring-data-jpa-query-3/README.md new file mode 100644 index 0000000000..246b6ebf3d --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/README.md @@ -0,0 +1,16 @@ +## Spring Data JPA - Query + +This module contains articles about querying data using Spring Data JPA. + +### Relevant Articles: +- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) +- More articles: [[<-- prev]](../spring-data-jpa-query-2) + +### Eclipse Config +After importing the project into Eclipse, you may see the following error: +"No persistence xml file found in project" + +This can be ignored: +- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" +Or: +- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator diff --git a/persistence-modules/spring-data-jpa-query-3/pom.xml b/persistence-modules/spring-data-jpa-query-3/pom.xml new file mode 100644 index 0000000000..66a4486bc8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + spring-data-jpa-query-3 + spring-data-jpa-query-3 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + + + org.springframework.boot + spring-boot-starter-test + test + + + + diff --git a/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java b/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java new file mode 100644 index 0000000000..48c29eda23 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.data.jpa.query; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class QueryApplication { + + public static void main(String[] args) { + SpringApplication.run(QueryApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java b/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java similarity index 99% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java rename to persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java index bb0e4e88df..1506285f8b 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java +++ b/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Article.java @@ -9,10 +9,13 @@ public class Article { @Id @GeneratedValue private Integer id; + @Temporal(TemporalType.DATE) private Date publicationDate; + @Temporal(TemporalType.TIME) private Date publicationTime; + @Temporal(TemporalType.TIMESTAMP) private Date creationDateTime; diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepository.java b/persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepository.java rename to persistence-modules/spring-data-jpa-query-3/src/main/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepository.java diff --git a/persistence-modules/spring-data-jpa-query-3/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-query-3/src/main/resources/application.properties new file mode 100644 index 0000000000..f37cce0b29 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.jpa.defer-datasource-initialization=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/resources/import_entities.sql b/persistence-modules/spring-data-jpa-query-3/src/main/resources/import_entities.sql similarity index 100% rename from persistence-modules/spring-data-jpa-query-2/src/main/resources/import_entities.sql rename to persistence-modules/spring-data-jpa-query-3/src/main/resources/import_entities.sql diff --git a/persistence-modules/spring-data-jpa-query-3/src/main/resources/logback.xml b/persistence-modules/spring-data-jpa-query-3/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-3/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java similarity index 98% rename from persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-3/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java index e00a340615..b97fbc5275 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-3/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java @@ -17,7 +17,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) -@DataJpaTest(properties="spring.sql.init.data-locations=classpath:import_entities.sql") +@DataJpaTest(properties="spring.sql.init.data-locations=classpath:import_entities.sql", showSql = false) public class ArticleRepositoryIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-jpa-query-3/src/test/resources/persistence-h2.properties b/persistence-modules/spring-data-jpa-query-3/src/test/resources/persistence-h2.properties new file mode 100644 index 0000000000..e5853ae523 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-3/src/test/resources/persistence-h2.properties @@ -0,0 +1,8 @@ +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:test +jdbc.user=sa +jdbc.pass= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties index 9bb870895d..eb0e519ef0 100644 --- a/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties @@ -1,2 +1,2 @@ -spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.defer-datasource-initialization=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java index 779ade7a3f..a73ad949db 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java @@ -16,8 +16,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @RunWith(SpringRunner.class) -@DataJpaTest - +@DataJpaTest(showSql = false) @Sql(scripts = "/test-aggregation-data.sql") public class SpringDataAggregateIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java index f082350019..d80380854d 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java @@ -26,8 +26,7 @@ import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; - -@DataJpaTest +@DataJpaTest(showSql = false) @RunWith(SpringRunner.class) public class PassengerRepositoryIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java index 24880a5dff..b6bf51ac65 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java @@ -14,7 +14,7 @@ import com.baeldung.entitygraph.model.Item; import com.baeldung.entitygraph.repository.CharacteristicsRepository; import com.baeldung.entitygraph.repository.ItemRepository; -@DataJpaTest +@DataJpaTest(showSql = false) @RunWith(SpringRunner.class) @Sql(scripts = "/entitygraph-data.sql") public class EntityGraphIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java index d99f6671a3..53f22ed0d1 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java index 9b0d23f3e4..e24b2ae4b7 100644 --- a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java @@ -13,10 +13,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) -@DataJpaTest +@DataJpaTest(showSql = false) @ActiveProfiles("joins") public class JpaJoinsIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-query/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md index 0a690fe5a5..6403510e6f 100644 --- a/persistence-modules/spring-data-jpa-repo-2/README.md +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -1,6 +1,9 @@ ## Spring Data JPA - Repositories ### Relevant Articles: + - [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Performance Difference Between save() and saveAll() in Spring Data](https://www.baeldung.com/spring-data-save-saveall) -- More articles: [[<-- prev]](/spring-data-jpa-repo/) +- [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries) +- [How to Access EntityManager with Spring Data](https://www.baeldung.com/spring-data-entitymanager) +- More articles: [[<-- prev]](../spring-data-jpa-repo) diff --git a/persistence-modules/spring-data-jpa-repo-2/pom.xml b/persistence-modules/spring-data-jpa-repo-2/pom.xml index 12e178dd49..748623c91a 100644 --- a/persistence-modules/spring-data-jpa-repo-2/pom.xml +++ b/persistence-modules/spring-data-jpa-repo-2/pom.xml @@ -14,7 +14,10 @@ - + + org.springframework.boot + spring-boot-starter-web + javax.persistence javax.persistence-api @@ -31,7 +34,7 @@ com.h2database h2 - + com.google.guava guava @@ -39,8 +42,4 @@ - - 29.0-jre - - \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java new file mode 100644 index 0000000000..f8f42aa67c --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.data.persistence.customrepository; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CustomRepositoryApplication { + + public static void main(String[] args) { + SpringApplication.run(CustomRepositoryApplication.class, args); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java new file mode 100644 index 0000000000..ba217577f3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java @@ -0,0 +1,55 @@ +package com.baeldung.spring.data.persistence.customrepository.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class User { + + @Id + @GeneratedValue + private Long id; + private String name; + private String email; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(email, user.email); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, email); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java new file mode 100644 index 0000000000..2c79e518b6 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; + +public interface CustomUserRepository { + + User customFindMethod(Long id); + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java new file mode 100644 index 0000000000..dc006580c1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.Objects; + +public class CustomUserRepositoryImpl implements CustomUserRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public User customFindMethod(Long id) { + return (User) entityManager.createQuery("FROM User u WHERE u.id = :id") + .setParameter("id", id) + .getSingleResult(); + } + + @PostConstruct + public void postConstruct() { + Objects.requireNonNull(entityManager); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java new file mode 100644 index 0000000000..d9f60015cc --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository, CustomUserRepository { + +} diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java similarity index 85% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java index 311aea3001..26a5723977 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.like; +package com.baeldung.spring.data.persistence.like; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java similarity index 94% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java index bba8bd35c4..f500b61a8a 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java @@ -1,4 +1,4 @@ -package com.baeldung.like.model; +package com.baeldung.spring.data.persistence.like.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java similarity index 90% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java index 241bdd3306..57befb5943 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java @@ -1,17 +1,16 @@ -package com.baeldung.like.repository; - -import java.util.List; +package com.baeldung.spring.data.persistence.like.repository; +import com.baeldung.spring.data.persistence.like.model.Movie; 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; +import java.util.List; public interface MovieRepository extends CrudRepository { List findByTitleContaining(String title); - + List findByTitleLike(String title); List findByTitleContains(String title); @@ -23,17 +22,17 @@ public interface MovieRepository extends CrudRepository { 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]}") diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java index 56ad918be3..46cb8d3453 100644 --- a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java @@ -1,5 +1,7 @@ package com.baeldung.spring.data.persistence.saveperformance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -12,6 +14,8 @@ import java.util.List; @SpringBootApplication public class BookApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(BookApplication.class); + @Autowired private BookRepository bookRepository; @@ -25,13 +29,13 @@ public class BookApplication { int bookCount = 10000; long start = System.currentTimeMillis(); - for(int i = 0; i < bookCount; i++) { + for (int i = 0; i < bookCount; i++) { bookRepository.save(new Book("Book " + i, "Author " + i)); } long end = System.currentTimeMillis(); bookRepository.deleteAll(); - System.out.println("It took " + (end - start) + "ms to execute save() for " + bookCount + " books"); + LOGGER.debug("It took {}ms to execute save() for {} books.", (end - start), bookCount); List bookList = new ArrayList<>(); for (int i = 0; i < bookCount; i++) { @@ -42,7 +46,7 @@ public class BookApplication { bookRepository.saveAll(bookList); end = System.currentTimeMillis(); - System.out.println("It took " + (end - start) + "ms to execute saveAll() with " + bookCount + " books\n"); + LOGGER.debug("It took {}ms to execute saveAll() with {}} books.", (end - start), bookCount); } } diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties index 339859a6e8..05cb7a13b9 100644 --- a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties @@ -2,7 +2,7 @@ jdbc.driverClassName=org.h2.Driver jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 jdbc.user=sa -jdbc.pass= +jdbc.pass=sa # hibernate.X hibernate.hbm2ddl.auto=create-drop diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java new file mode 100644 index 0000000000..ed54225a14 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.data.persistence.customrepository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; +import com.baeldung.spring.data.persistence.customrepository.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(classes = CustomRepositoryApplication.class) +class CustomRepositoryUnitTest { + + @Autowired + private UserRepository userRepository; + + @Test + void givenCustomRepository_whenInvokeCustomFindMethod_thenEntityIsFound() { + User user = new User(); + user.setEmail("foo@gmail.com"); + user.setName("userName"); + + User persistedUser = userRepository.save(user); + + assertEquals(persistedUser, userRepository.customFindMethod(user.getId())); + } +} diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java similarity index 91% rename from persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java index cc96b638ab..291926c127 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java @@ -1,7 +1,7 @@ -package com.baeldung.like; +package com.baeldung.spring.data.persistence.like; -import com.baeldung.like.model.Movie; -import com.baeldung.like.repository.MovieRepository; +import com.baeldung.spring.data.persistence.like.model.Movie; +import com.baeldung.spring.data.persistence.like.repository.MovieRepository; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -9,6 +9,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.context.junit4.SpringRunner; +import javax.sql.DataSource; import java.util.List; import static org.junit.Assert.assertEquals; @@ -22,11 +23,14 @@ public class MovieRepositoryIntegrationTest { @Autowired private MovieRepository movieRepository; + @Autowired + private DataSource dataSource; + @Test public void givenPartialTitle_WhenFindByTitleContaining_ThenMoviesShouldReturn() { List results = movieRepository.findByTitleContaining("in"); assertEquals(3, results.size()); - + results = movieRepository.findByTitleLike("%in%"); assertEquals(3, results.size()); @@ -60,25 +64,25 @@ public class MovieRepositoryIntegrationTest { 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%"); diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java index 141844fa11..21990afb5e 100644 --- a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java @@ -7,6 +7,8 @@ import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import javax.sql.DataSource; + @RunWith(SpringRunner.class) @ContextConfiguration(classes = PersistenceConfig.class) public class FooServiceIntegrationTest { @@ -14,6 +16,9 @@ public class FooServiceIntegrationTest { @Autowired private IFooService service; + @Autowired + private DataSource dataSource; + @Test(expected = DataIntegrityViolationException.class) public final void whenInvalidEntityIsCreated_thenDataException() { service.create(new Foo()); diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-cleanup.sql b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-cleanup.sql similarity index 100% rename from persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-cleanup.sql rename to persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-cleanup.sql diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-data.sql b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-data.sql similarity index 100% rename from persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-data.sql rename to persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-data.sql diff --git a/persistence-modules/spring-data-jpa-repo/README.md b/persistence-modules/spring-data-jpa-repo/README.md index 1a95340a97..43097a8c1e 100644 --- a/persistence-modules/spring-data-jpa-repo/README.md +++ b/persistence-modules/spring-data-jpa-repo/README.md @@ -5,13 +5,12 @@ This module contains articles about repositories in Spring Data JPA ### Relevant Articles: - [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries) - [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries) -- [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries) - [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) - [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories) - [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories) - [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators) - [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) -- More articles: [[--> next]](/spring-data-jpa-repo-2/) +- More articles: [[--> next]](../spring-data-jpa-repo-2) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties index ae1afe6e98..1a370121c5 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.defer-datasource-initialization=true #MySql #spring.datasource.url=jdbc:mysql://localhost:3306/baeldung diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java index fe02f79a56..34de77a2b3 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java @@ -21,7 +21,7 @@ import com.baeldung.boot.domain.Location; import com.baeldung.boot.domain.Store; @RunWith(SpringRunner.class) -@DataJpaTest(properties="spring.sql.init.data-locations=classpath:import_entities.sql") +@DataJpaTest(properties="spring.sql.init.data-locations=classpath:import_entities.sql", showSql = false) public class JpaRepositoriesIntegrationTest { @Autowired private LocationRepository locationRepository; diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java index 37fcef7dab..fd06710084 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java @@ -18,7 +18,7 @@ import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.entity.Passenger; -@DataJpaTest +@DataJpaTest(showSql = false) @RunWith(SpringRunner.class) public class PassengerRepositoryIntegrationTest { diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-repo/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb-reactive/pom.xml b/persistence-modules/spring-data-mongodb-reactive/pom.xml index c1398ca80d..ac2bf14635 100644 --- a/persistence-modules/spring-data-mongodb-reactive/pom.xml +++ b/persistence-modules/spring-data-mongodb-reactive/pom.xml @@ -57,6 +57,7 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo + ${embed.mongo.version} test @@ -71,7 +72,6 @@ com.h2database h2 - ${h2.version} org.apache.httpcomponents @@ -124,10 +124,10 @@ - 5.2.2.RELEASE + 5.3.15 4.5.2 - 1.4.200 3.3.1.RELEASE + 3.2.6 \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb-reactive/src/test/resources/application.properties b/persistence-modules/spring-data-mongodb-reactive/src/test/resources/application.properties new file mode 100644 index 0000000000..a5b5fb9804 --- /dev/null +++ b/persistence-modules/spring-data-mongodb-reactive/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.mongodb.embedded.version=4.4.9 \ No newline at end of file diff --git a/persistence-modules/spring-data-redis/pom.xml b/persistence-modules/spring-data-redis/pom.xml index 5e17f27c06..330f0d975a 100644 --- a/persistence-modules/spring-data-redis/pom.xml +++ b/persistence-modules/spring-data-redis/pom.xml @@ -42,10 +42,6 @@ spring-boot-starter-test test - - org.junit.jupiter - junit-jupiter-api - org.junit.platform junit-platform-runner @@ -78,7 +74,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} true false diff --git a/persistence-modules/spring-data-solr/pom.xml b/persistence-modules/spring-data-solr/pom.xml index d7523e6de2..c68c405137 100644 --- a/persistence-modules/spring-data-solr/pom.xml +++ b/persistence-modules/spring-data-solr/pom.xml @@ -45,7 +45,7 @@ - 2.0.5.RELEASE + 4.3.14 \ No newline at end of file diff --git a/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java b/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java index 1fe1e5468b..54a9816114 100644 --- a/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java +++ b/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java @@ -9,13 +9,13 @@ import org.springframework.data.solr.core.SolrTemplate; import org.springframework.data.solr.repository.config.EnableSolrRepositories; @Configuration -@EnableSolrRepositories(basePackages = "com.baeldung.spring.data.solr.repository", namedQueriesLocation = "classpath:solr-named-queries.properties", multicoreSupport = true) +@EnableSolrRepositories(basePackages = "com.baeldung.spring.data.solr.repository", namedQueriesLocation = "classpath:solr-named-queries.properties") @ComponentScan public class SolrConfig { @Bean public SolrClient solrClient() { - return new HttpSolrClient("http://localhost:8983/solr"); + return new HttpSolrClient.Builder("http://localhost:8983/solr").build(); } @Bean diff --git a/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java b/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java index 5649cd7888..677073a58b 100644 --- a/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java +++ b/persistence-modules/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java @@ -1,6 +1,7 @@ package com.baeldung.spring.data.solr.repository; import java.util.List; +import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -11,6 +12,8 @@ import com.baeldung.spring.data.solr.model.Product; public interface ProductRepository extends SolrCrudRepository { + public Optional findById(String id); + public List findByName(String name); @Query("id:*?0* OR name:*?0*") diff --git a/persistence-modules/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryLiveTest.java b/persistence-modules/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryLiveTest.java index f86adcdc8a..2208ffadc0 100644 --- a/persistence-modules/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryLiveTest.java +++ b/persistence-modules/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.data.solr.repo; + package com.baeldung.spring.data.solr.repo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -36,7 +36,7 @@ public class ProductRepositoryLiveTest { product.setId("P000089998"); product.setName("Desk"); productRepository.save(product); - final Product retrievedProduct = productRepository.findOne(product.getId()); + final Product retrievedProduct = productRepository.findById(product.getId()).get(); assertEquals(product.getId(), retrievedProduct.getId()); } @@ -51,7 +51,7 @@ public class ProductRepositoryLiveTest { product.setName("Shirt"); productRepository.save(product); - final Product retrievedProduct = productRepository.findOne(product.getId()); + final Product retrievedProduct = productRepository.findById(product.getId()).get(); assertEquals(product.getName(), retrievedProduct.getName()); } @@ -64,7 +64,7 @@ public class ProductRepositoryLiveTest { productRepository.delete(product); - Product retrievedProduct = productRepository.findOne(product.getId()); + Product retrievedProduct = productRepository.findById(product.getId()).get(); assertNull(retrievedProduct); } @@ -97,7 +97,7 @@ public class ProductRepositoryLiveTest { wirelessCharger.setName("Phone Charging Cable"); productRepository.save(wirelessCharger); - Page result = productRepository.findByCustomQuery("Phone", new PageRequest(0, 10)); + Page result = productRepository.findByCustomQuery("Phone", PageRequest.of(0, 10)); assertEquals(3, result.getNumberOfElements()); } @@ -118,7 +118,7 @@ public class ProductRepositoryLiveTest { wirelessCharger.setName("Phone Charging Cable"); productRepository.save(wirelessCharger); - Page result = productRepository.findByNamedQuery("one", new PageRequest(0, 10)); + Page result = productRepository.findByNamedQuery("one", PageRequest.of(0, 10)); assertEquals(3, result.getNumberOfElements()); } diff --git a/persistence-modules/spring-hibernate-3/pom.xml b/persistence-modules/spring-hibernate-3/pom.xml index 9b143597c7..306c4995d2 100644 --- a/persistence-modules/spring-hibernate-3/pom.xml +++ b/persistence-modules/spring-hibernate-3/pom.xml @@ -81,8 +81,6 @@ 3.6.10.Final 5.1.40 8.5.8 - - 19.0 \ No newline at end of file diff --git a/persistence-modules/spring-hibernate-5/pom.xml b/persistence-modules/spring-hibernate-5/pom.xml index caa1598af4..d0fa23504c 100644 --- a/persistence-modules/spring-hibernate-5/pom.xml +++ b/persistence-modules/spring-hibernate-5/pom.xml @@ -122,8 +122,6 @@ 9.0.0.M26 1.1 2.3.4 - - 21.0 \ No newline at end of file diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/dynamicupdate/DynamicUpdateConfig.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/dynamicupdate/DynamicUpdateConfig.java index 4871a3d1e2..23e28a9e3b 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/dynamicupdate/DynamicUpdateConfig.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/dynamicupdate/DynamicUpdateConfig.java @@ -74,7 +74,7 @@ public class DynamicUpdateConfig { Properties properties = new Properties(); properties.setProperty("hibernate.hbm2ddl.auto", Preconditions.checkNotNull(env.getProperty("hibernate.hbm2ddl.auto"))); properties.setProperty("hibernate.dialect", Preconditions.checkNotNull(env.getProperty("hibernate.dialect"))); - properties.setProperty("hibernate.show_sql", "true"); + properties.setProperty("hibernate.show_sql", "false"); return properties; } } \ No newline at end of file diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java index 722f0251d1..aee4206e53 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java @@ -6,8 +6,12 @@ import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class HibernateUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { @@ -20,7 +24,7 @@ public class HibernateUtil { ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); return configuration.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { - System.out.println("Initial SessionFactory creation failed." + ex); + LOGGER.debug("Initial SessionFactory creation failed.", ex); throw new ExceptionInInitializerError(ex); } } diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java index 5f489dd027..29e8d7515a 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java @@ -6,8 +6,12 @@ import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import com.baeldung.hibernate.manytomany.model.Employee; import com.baeldung.hibernate.manytomany.model.Project; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class HibernateUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); private static SessionFactory sessionFactory; private static SessionFactory buildSessionFactory() { @@ -17,25 +21,25 @@ public class HibernateUtil { configuration.addAnnotatedClass(Employee.class); configuration.addAnnotatedClass(Project.class); configuration.configure("manytomany.cfg.xml"); - System.out.println("Hibernate Annotation Configuration loaded"); + LOGGER.debug("Hibernate Annotation Configuration loaded"); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()) - .build(); - System.out.println("Hibernate Annotation serviceRegistry created"); + .build(); + LOGGER.debug("Hibernate Annotation serviceRegistry created"); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); return sessionFactory; } catch (Throwable ex) { - System.err.println("Initial SessionFactory creation failed." + ex); - ex.printStackTrace(); + LOGGER.error("Initial SessionFactory creation failed.", ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { - if (sessionFactory == null) + if (sessionFactory == null) { sessionFactory = buildSessionFactory(); + } return sessionFactory; } } diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java index 44cbfadb25..b8e7e1b2fd 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java @@ -63,7 +63,7 @@ public class PersistenceConfig { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - hibernateProperties.setProperty("hibernate.show_sql", "true"); + hibernateProperties.setProperty("hibernate.show_sql", "false"); return hibernateProperties; } diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/spring/PersistenceConfig.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/spring/PersistenceConfig.java index 74ac0a269e..159d6e2e8e 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/spring/PersistenceConfig.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -71,7 +71,7 @@ public class PersistenceConfig { hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - hibernateProperties.setProperty("hibernate.show_sql", "true"); + hibernateProperties.setProperty("hibernate.show_sql", "false"); // Envers properties hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); diff --git a/persistence-modules/spring-hibernate-5/src/main/resources/immutable.cfg.xml b/persistence-modules/spring-hibernate-5/src/main/resources/immutable.cfg.xml index a572ebeac2..4e55b4632f 100644 --- a/persistence-modules/spring-hibernate-5/src/main/resources/immutable.cfg.xml +++ b/persistence-modules/spring-hibernate-5/src/main/resources/immutable.cfg.xml @@ -23,7 +23,7 @@ thread - true + false update diff --git a/persistence-modules/spring-hibernate-5/src/main/resources/manytomany.cfg.xml b/persistence-modules/spring-hibernate-5/src/main/resources/manytomany.cfg.xml index 3c753a89af..315e2e3118 100644 --- a/persistence-modules/spring-hibernate-5/src/main/resources/manytomany.cfg.xml +++ b/persistence-modules/spring-hibernate-5/src/main/resources/manytomany.cfg.xml @@ -10,6 +10,6 @@ tutorialuser org.hibernate.dialect.MySQLDialect thread - true + false diff --git a/persistence-modules/spring-hibernate-5/src/test/resources/manytomany.cfg.xml b/persistence-modules/spring-hibernate-5/src/test/resources/manytomany.cfg.xml index a7a23ec70d..2ca23d57d3 100644 --- a/persistence-modules/spring-hibernate-5/src/test/resources/manytomany.cfg.xml +++ b/persistence-modules/spring-hibernate-5/src/test/resources/manytomany.cfg.xml @@ -10,7 +10,7 @@ sa org.hibernate.dialect.H2Dialect thread - true + false create-drop diff --git a/persistence-modules/spring-jdbc/src/test/java/com/baeldung/spring/jdbc/template/guide/EmployeeDAOIntegrationTest.java b/persistence-modules/spring-jdbc/src/test/java/com/baeldung/spring/jdbc/template/guide/EmployeeDAOIntegrationTest.java index c29d5c4534..b382895143 100644 --- a/persistence-modules/spring-jdbc/src/test/java/com/baeldung/spring/jdbc/template/guide/EmployeeDAOIntegrationTest.java +++ b/persistence-modules/spring-jdbc/src/test/java/com/baeldung/spring/jdbc/template/guide/EmployeeDAOIntegrationTest.java @@ -9,6 +9,8 @@ import com.baeldung.spring.jdbc.template.guide.config.SpringJdbcConfig; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; import org.springframework.test.context.ContextConfiguration; @@ -19,6 +21,8 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @ContextConfiguration(classes = { SpringJdbcConfig.class }, loader = AnnotationConfigContextLoader.class) public class EmployeeDAOIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeDAOIntegrationTest.class); + @Autowired private EmployeeDAO employeeDao; @@ -70,7 +74,7 @@ public class EmployeeDAOIntegrationTest { try { employeeDao.addEmplyee(7); } catch (final DuplicateKeyException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage(), e); Assert.assertTrue(e.getMessage().contains("Custome Exception translator - Integrity contraint voilation.")); } } diff --git a/persistence-modules/spring-jdbc/src/test/resources/logback-test.xml b/persistence-modules/spring-jdbc/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-jdbc/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-jooq/pom.xml b/persistence-modules/spring-jooq/pom.xml index 4c195a6c92..c842922fe5 100644 --- a/persistence-modules/spring-jooq/pom.xml +++ b/persistence-modules/spring-jooq/pom.xml @@ -76,7 +76,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} 0 diff --git a/persistence-modules/spring-jpa-2/pom.xml b/persistence-modules/spring-jpa-2/pom.xml index 16168036be..19f5a8acc2 100644 --- a/persistence-modules/spring-jpa-2/pom.xml +++ b/persistence-modules/spring-jpa-2/pom.xml @@ -84,8 +84,6 @@ 2.2.6.RELEASE 9.0.0.M26 - - 21.0 \ No newline at end of file diff --git a/persistence-modules/spring-jpa-2/src/main/resources/persistence-h2.properties b/persistence-modules/spring-jpa-2/src/main/resources/persistence-h2.properties index 716a96fde3..b429ce3a16 100644 --- a/persistence-modules/spring-jpa-2/src/main/resources/persistence-h2.properties +++ b/persistence-modules/spring-jpa-2/src/main/resources/persistence-h2.properties @@ -6,7 +6,7 @@ jdbc.pass= # hibernate.X hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.cache.use_second_level_cache=true hibernate.cache.use_query_cache=true diff --git a/persistence-modules/spring-jpa-2/src/test/resources/logback-test.xml b/persistence-modules/spring-jpa-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-jpa-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-jpa-2/src/test/resources/manytomany/test.properties b/persistence-modules/spring-jpa-2/src/test/resources/manytomany/test.properties index 9e4236a6c2..db92a1b8c1 100644 --- a/persistence-modules/spring-jpa-2/src/test/resources/manytomany/test.properties +++ b/persistence-modules/spring-jpa-2/src/test/resources/manytomany/test.properties @@ -2,5 +2,5 @@ jdbc.driverClassName=org.h2.Driver jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=validate diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index e849ec4a83..aa9e833260 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -5,8 +5,8 @@ - [JPA Pagination](https://www.baeldung.com/jpa-pagination) - [Sorting with JPA](https://www.baeldung.com/jpa-sort) - [Self-Contained Testing Using an In-Memory Database](https://www.baeldung.com/spring-jpa-test-in-memory-database) -- [Obtaining Auto-generated Keys in Spring JDBC](https://www.baeldung.com/spring-jdbc-autogenerated-keys) - [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) +- [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source) - More articles: [[next -->]](/spring-jpa-2) ### Eclipse Config diff --git a/persistence-modules/spring-jpa/pom.xml b/persistence-modules/spring-jpa/pom.xml index 1dca2baa98..ddc753db86 100644 --- a/persistence-modules/spring-jpa/pom.xml +++ b/persistence-modules/spring-jpa/pom.xml @@ -98,11 +98,6 @@ guava ${guava.version} - - org.assertj - assertj-core - ${assertj.version} - org.apache.commons @@ -130,9 +125,6 @@ 6.0.15.Final 1.4.01 2.2.5 - - 21.0 - 3.8.0 \ No newline at end of file diff --git a/persistence-modules/spring-jpa/src/main/resources/persistence-h2.properties b/persistence-modules/spring-jpa/src/main/resources/persistence-h2.properties index a3060cc796..72b51f02b7 100644 --- a/persistence-modules/spring-jpa/src/main/resources/persistence-h2.properties +++ b/persistence-modules/spring-jpa/src/main/resources/persistence-h2.properties @@ -6,5 +6,5 @@ jdbc.pass= # hibernate.X hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/persistence-modules/spring-jpa/src/main/resources/persistence-student-h2.properties b/persistence-modules/spring-jpa/src/main/resources/persistence-student-h2.properties index 405e6ff109..a5d2bec189 100644 --- a/persistence-modules/spring-jpa/src/main/resources/persistence-student-h2.properties +++ b/persistence-modules/spring-jpa/src/main/resources/persistence-student-h2.properties @@ -6,7 +6,7 @@ jdbc.pass= # hibernate.X hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.cache.use_second_level_cache=false hibernate.cache.use_query_cache=false \ No newline at end of file diff --git a/persistence-modules/spring-jpa/src/main/resources/persistence-student.properties b/persistence-modules/spring-jpa/src/main/resources/persistence-student.properties index d4c82420de..9a06518238 100644 --- a/persistence-modules/spring-jpa/src/main/resources/persistence-student.properties +++ b/persistence-modules/spring-jpa/src/main/resources/persistence-student.properties @@ -4,7 +4,7 @@ jdbc.user=tutorialuser jdbc.pass=tutorialpass hibernate.dialect=org.hibernate.dialect.MySQL5Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop hibernate.cache.use_second_level_cache=false diff --git a/persistence-modules/spring-jpa/src/test/java/META-INF/persistence.xml b/persistence-modules/spring-jpa/src/test/java/META-INF/persistence.xml index 495f076fef..76a3b61399 100644 --- a/persistence-modules/spring-jpa/src/test/java/META-INF/persistence.xml +++ b/persistence-modules/spring-jpa/src/test/java/META-INF/persistence.xml @@ -11,7 +11,7 @@ - + diff --git a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java index fbda459d65..66f20a6724 100644 --- a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java @@ -20,6 +20,8 @@ import com.baeldung.persistence.model.Foo; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -31,6 +33,8 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @DirtiesContext public class FooPaginationPersistenceIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(FooPaginationPersistenceIntegrationTest.class); + @PersistenceContext private EntityManager entityManager; @@ -137,7 +141,7 @@ public class FooPaginationPersistenceIntegrationTest { typedQuery = entityManager.createQuery(select); typedQuery.setFirstResult(pageNumber - 1); typedQuery.setMaxResults(pageSize); - System.out.println("Current page: " + typedQuery.getResultList()); + LOGGER.debug("Current page: {}", typedQuery.getResultList()); pageNumber += pageSize; } diff --git a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java index c3db45ab41..8d1f94edf8 100644 --- a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java @@ -15,6 +15,8 @@ import com.baeldung.persistence.model.Bar; import com.baeldung.persistence.model.Foo; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -26,6 +28,8 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @SuppressWarnings("unchecked") public class FooServiceSortingIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(FooServiceSortingIntegrationTest.class); + @PersistenceContext private EntityManager entityManager; @@ -37,7 +41,7 @@ public class FooServiceSortingIntegrationTest { final Query sortQuery = entityManager.createQuery(jql); final List fooList = sortQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + LOGGER.debug("Name:{}-------Id:{}", foo.getName(), foo.getId()); } } @@ -47,7 +51,7 @@ public class FooServiceSortingIntegrationTest { final Query sortQuery = entityManager.createQuery(jql); final List fooList = sortQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + LOGGER.debug("Name:{}-------Id:{}", foo.getName(), foo.getId()); } } @@ -57,7 +61,7 @@ public class FooServiceSortingIntegrationTest { final Query sortQuery = entityManager.createQuery(jql); final List fooList = sortQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + LOGGER.debug("Name:{}-------Id:{}", foo.getName(), foo.getId()); } } @@ -67,9 +71,9 @@ public class FooServiceSortingIntegrationTest { final Query barJoinQuery = entityManager.createQuery(jql); final List fooList = barJoinQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); + LOGGER.debug("Name:{}", foo.getName()); if (foo.getBar() != null) { - System.out.print("-------BarId:" + foo.getBar().getId()); + LOGGER.debug("-------BarId:{}", foo.getBar().getId()); } } } @@ -80,9 +84,9 @@ public class FooServiceSortingIntegrationTest { final Query barQuery = entityManager.createQuery(jql); final List barList = barQuery.getResultList(); for (final Bar bar : barList) { - System.out.println("Bar Id:" + bar.getId()); + LOGGER.debug("Bar Id:{}", bar.getId()); for (final Foo foo : bar.getFooList()) { - System.out.println("FooName:" + foo.getName()); + LOGGER.debug("FooName:{}", foo.getName()); } } } @@ -97,7 +101,7 @@ public class FooServiceSortingIntegrationTest { final TypedQuery typedQuery = entityManager.createQuery(select); final List fooList = typedQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId()); + LOGGER.debug("Name:{}-------Id:{}", foo.getName(), foo.getId()); } } @@ -111,7 +115,7 @@ public class FooServiceSortingIntegrationTest { final TypedQuery typedQuery = entityManager.createQuery(select); final List fooList = typedQuery.getResultList(); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + LOGGER.debug("Name:{}-------Id:{}", foo.getName(), foo.getId()); } } diff --git a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java index 103321fc64..b19259d9df 100644 --- a/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java @@ -13,6 +13,8 @@ import com.baeldung.config.PersistenceJPAConfig; import com.baeldung.persistence.model.Foo; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -24,6 +26,8 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @DirtiesContext public class FooServiceSortingWitNullsManualIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(FooServiceSortingWitNullsManualIntegrationTest.class); + @PersistenceContext private EntityManager entityManager; @@ -43,7 +47,7 @@ public class FooServiceSortingWitNullsManualIntegrationTest { final List fooList = sortQuery.getResultList(); assertNull(fooList.get(fooList.toArray().length - 1).getName()); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); + LOGGER.debug("Name:{}", foo.getName()); } } @@ -57,7 +61,7 @@ public class FooServiceSortingWitNullsManualIntegrationTest { final List fooList = sortQuery.getResultList(); assertNull(fooList.get(0).getName()); for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); + LOGGER.debug("Name:{}", foo.getName()); } } diff --git a/persistence-modules/spring-jpa/src/test/resources/persistence-student.properties b/persistence-modules/spring-jpa/src/test/resources/persistence-student.properties index 3b6b580630..9ca389d6ab 100644 --- a/persistence-modules/spring-jpa/src/test/resources/persistence-student.properties +++ b/persistence-modules/spring-jpa/src/test/resources/persistence-student.properties @@ -2,7 +2,7 @@ jdbc.driverClassName=org.h2.Driver jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true +hibernate.show_sql=false hibernate.hbm2ddl.auto=create hibernate.cache.use_second_level_cache=false diff --git a/persistence-modules/spring-mybatis/pom.xml b/persistence-modules/spring-mybatis/pom.xml index 1a55e76900..65a8581f97 100644 --- a/persistence-modules/spring-mybatis/pom.xml +++ b/persistence-modules/spring-mybatis/pom.xml @@ -64,12 +64,6 @@ ${org.springframework.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - @@ -84,14 +78,12 @@ - 5.3.8 + 5.3.15 - 2.0.2 + 2.0.6 3.5.2 - 2.1.0 + 2.2.0 1.4.197 - - 3.8.0 \ No newline at end of file diff --git a/persistence-modules/spring-mybatis/src/main/resources/logback.xml b/persistence-modules/spring-mybatis/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/persistence-modules/spring-mybatis/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/persistence-modules/spring-mybatis/src/test/resources/logback-test.xml b/persistence-modules/spring-mybatis/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-mybatis/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml index 437a439b99..d9b832df2d 100644 --- a/persistence-modules/spring-persistence-simple/pom.xml +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -76,12 +76,6 @@ test ${spring-boot-starter.version} - - org.mockito - mockito-core - ${mockito.version} - test - @@ -92,11 +86,8 @@ 2.2 1.3 2.2.7.RELEASE - 1.4.200 0.23.0 - - 3.3.3 \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/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/persistence-modules/spring-persistence-simple/src/test/resources/logback-test.xml b/persistence-modules/spring-persistence-simple/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index f2a53f38b7..99217774e9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,9 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + + spring-5-webflux-2 + parent-modules pom @@ -58,6 +61,12 @@ ${junit-jupiter.version} test + + org.assertj + assertj-core + ${assertj.version} + test + org.hamcrest hamcrest @@ -113,11 +122,6 @@ - - org.junit.platform - junit-platform-surefire-provider - ${junit-platform-surefire-provider.version} - org.junit.jupiter junit-jupiter-engine @@ -294,7 +298,6 @@ default-first - org.apache.maven.plugins maven-surefire-plugin @@ -314,6 +317,9 @@ **/JdbcTest.java **/*LiveTest.java + + ${tutorialsproject.basedir}/logback-config.xml + @@ -347,7 +353,7 @@ apache-cxf apache-kafka apache-libraries - apache-olingo/olingo2 + apache-olingo apache-poi apache-rocketmq apache-shiro @@ -416,6 +422,7 @@ graphql/graphql-java + graphql/graphql-dgs grpc gson guava-modules @@ -472,7 +479,6 @@ json-path jsoup jta - junit5 kubernetes ksqldb @@ -498,6 +504,7 @@ linkrest logging-modules lombok + lombok-2 lombok-custom lucene @@ -552,7 +559,6 @@ atomikos reactive-systems slack - spring-webflux-threads @@ -581,6 +587,9 @@ **/*JdbcTest.java **/*LiveTest.java + + ${tutorialsproject.basedir}/logback-config.xml + @@ -606,15 +615,19 @@ spring-5-data-reactive spring-5-reactive spring-5-reactive-2 + spring-5-reactive-3 spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security spring-5-webflux + spring-5-webflux-2 + spring-reactive spring-activiti spring-akka spring-amqp spring-aop + spring-aop-2 spring-apache-camel spring-batch @@ -643,6 +656,7 @@ spring-data-rest-querydsl spring-di spring-di-2 + spring-di-3 spring-drools spring-ejb @@ -764,6 +778,9 @@ libraries-5 libraries-6 + spring-boot-modules/spring-boot-react + spring-ejb/ejb-beans + vaadin vavr vavr-2 @@ -787,6 +804,9 @@ **/*IntegrationTest.java **/*IntTest.java + + ${tutorialsproject.basedir}/logback-config.xml + @@ -819,7 +839,7 @@ apache-cxf apache-kafka apache-libraries - apache-olingo/olingo2 + apache-olingo apache-poi apache-rocketmq apache-shiro @@ -968,6 +988,7 @@ linkrest logging-modules lombok + lombok-2 lombok-custom lucene @@ -1022,7 +1043,6 @@ atomikos reactive-systems slack - spring-webflux-threads @@ -1044,6 +1064,9 @@ **/*IntegrationTest.java **/*IntTest.java + + ${tutorialsproject.basedir}/logback-config.xml + @@ -1068,15 +1091,18 @@ spring-5-data-reactive spring-5-reactive spring-5-reactive-2 + spring-5-reactive-3 spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security spring-5-webflux + spring-reactive spring-activiti spring-akka spring-amqp spring-aop + spring-aop-2 spring-apache-camel spring-batch @@ -1217,6 +1243,9 @@ libraries-5 libraries-6 + spring-boot-modules/spring-boot-react + spring-ejb/ejb-beans + vaadin vavr vavr-2 @@ -1304,12 +1333,19 @@ core-java-modules/core-java-io-conversions-2 core-java-modules/core-java-jpms core-java-modules/core-java-os + core-java-modules/core-java-string-algorithms-3 core-java-modules/core-java-string-operations-3 + core-java-modules/core-java-string-operations-4 core-java-modules/core-java-time-measurements + core-java-modules/core-java-networking-3 core-java-modules/multimodulemavenproject persistence-modules/sirix + persistence-modules/spring-data-cassandra-2 quarkus-vs-springboot - spring-boot-modules/spring-boot-cassandre + quarkus-jandex + spring-boot-modules/spring-boot-cassandre + spring-boot-modules/spring-boot-camel + testing-modules/testing-assertions @@ -1356,12 +1392,18 @@ core-java-modules/core-java-jpms core-java-modules/core-java-os core-java-modules/core-java-string-operations-3 + core-java-modules/core-java-string-operations-4 core-java-modules/core-java-time-measurements + core-java-modules/core-java-networking-3 core-java-modules/multimodulemavenproject core-java-modules/core-java-strings persistence-modules/sirix + persistence-modules/spring-data-cassandra-2 quarkus-vs-springboot - spring-boot-modules/spring-boot-cassandre + quarkus-jandex + spring-boot-modules/spring-boot-cassandre + spring-boot-modules/spring-boot-camel + testing-modules/testing-assertions @@ -1388,9 +1430,10 @@ 4.13.2 + 3.21.0 2.2 1.3 - 3.3.0 + 4.1.0 1.11.20 @@ -1398,8 +1441,7 @@ 1.2.6 - - 2.21.0 + 2.22.2 3.8.1 3.0.0 1.8 @@ -1408,6 +1450,7 @@ 1.33 1.33 2.21.0 + 4.4 2.11.0 2.6 3.12.0 @@ -1430,7 +1473,8 @@ 3.13.0 1.18.20 - 1.4.197 + 1.4.200 + 31.0.1-jre diff --git a/quarkus-jandex/README.md b/quarkus-jandex/README.md new file mode 100644 index 0000000000..cca5fa7714 --- /dev/null +++ b/quarkus-jandex/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Quarkus Bean Discovery With Jandex Indexing](https://www.baeldung.com/quarkus-bean-discovery-index) diff --git a/quarkus-jandex/hello-app/.dockerignore b/quarkus-jandex/hello-app/.dockerignore new file mode 100644 index 0000000000..94810d006e --- /dev/null +++ b/quarkus-jandex/hello-app/.dockerignore @@ -0,0 +1,5 @@ +* +!target/*-runner +!target/*-runner.jar +!target/lib/* +!target/quarkus-app/* \ No newline at end of file diff --git a/quarkus-jandex/hello-app/.gitignore b/quarkus-jandex/hello-app/.gitignore new file mode 100644 index 0000000000..bdf57ce3b4 --- /dev/null +++ b/quarkus-jandex/hello-app/.gitignore @@ -0,0 +1,39 @@ +#Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +release.properties + +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode +.factorypath + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +# Local environment +.env diff --git a/quarkus-jandex/hello-app/.mvn/wrapper/MavenWrapperDownloader.java b/quarkus-jandex/hello-app/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..c39041cdf6 --- /dev/null +++ b/quarkus-jandex/hello-app/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,114 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println("- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/quarkus-jandex/hello-app/.mvn/wrapper/maven-wrapper.properties b/quarkus-jandex/hello-app/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..ffdc10e59f --- /dev/null +++ b/quarkus-jandex/hello-app/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/quarkus-jandex/hello-app/README.md b/quarkus-jandex/hello-app/README.md new file mode 100644 index 0000000000..769709eb00 --- /dev/null +++ b/quarkus-jandex/hello-app/README.md @@ -0,0 +1,51 @@ +# Hello App with Quarkus + +## Running the application in dev mode + +You can run your application in dev mode that enables live coding using: + +```shell script +./mvnw compile quarkus:dev +``` + +You can then find the app using `http://localhost:8080`. + +> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/. + +## Packaging and running the application + +The application can be packaged using: + +```shell script +./mvnw package +``` + +It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. + +The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. + +If you want to build an _über-jar_, execute the following command: + +```shell script +./mvnw package -Dquarkus.package.type=uber-jar +``` + +The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. + +## Creating a native executable + +You can create a native executable using: + +```shell script +./mvnw package -Pnative +``` + +Or, if you don't have GraalVM installed, you can run the native executable build in a container using: + +```shell script +./mvnw package -Pnative -Dquarkus.native.container-build=true +``` + +You can then execute your native executable with: `./target/quarkus-sample-1.0-SNAPSHOT-runner` + +If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.html. diff --git a/quarkus-jandex/hello-app/mvnw b/quarkus-jandex/hello-app/mvnw new file mode 100644 index 0000000000..a16b5431b4 --- /dev/null +++ b/quarkus-jandex/hello-app/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/quarkus-jandex/hello-app/mvnw.cmd b/quarkus-jandex/hello-app/mvnw.cmd new file mode 100644 index 0000000000..c8d43372c9 --- /dev/null +++ b/quarkus-jandex/hello-app/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/quarkus-jandex/hello-app/pom.xml b/quarkus-jandex/hello-app/pom.xml new file mode 100644 index 0000000000..0255a6636b --- /dev/null +++ b/quarkus-jandex/hello-app/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + hello-app + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + ${project.groupId} + hello-service + ${project.version} + + + ${project.groupId} + hello-sender-beans-xml + ${project.version} + + + ${project.groupId} + hello-sender-maven-plugin + ${project.version} + + + ${project.groupId} + hello-sender-application-properties + ${project.version} + + + ${project.groupId} + hello-sender-undetected + ${project.version} + + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + ${maven.compiler.parameters} + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + native + + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + + + \ No newline at end of file diff --git a/quarkus-jandex/hello-app/src/main/docker/Dockerfile.jvm b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000000..3eb1b4de84 --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.jvm @@ -0,0 +1,55 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/quarkus-sample-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-sample-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-sample-jvm +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=1001 target/quarkus-app/*.jar /deployments/ +COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ +COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] + diff --git a/quarkus-jandex/hello-app/src/main/docker/Dockerfile.legacy-jar b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.legacy-jar new file mode 100644 index 0000000000..f32188a45d --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.legacy-jar @@ -0,0 +1,51 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package -Dquarkus.package.type=legacy-jar +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/quarkus-sample-legacy-jar . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-sample-legacy-jar +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-sample-legacy-jar +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/app.jar + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] diff --git a/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native new file mode 100644 index 0000000000..4fa16507fe --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native @@ -0,0 +1,27 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +# +# Before building the container image run: +# +# ./mvnw package -Pnative +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-sample . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-sample +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native-distroless b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native-distroless new file mode 100644 index 0000000000..86370b0a0b --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/docker/Dockerfile.native-distroless @@ -0,0 +1,23 @@ +#### +# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode +# +# Before building the container image run: +# +# ./mvnw package -Pnative +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native-distroless -t quarkus/quarkus-sample . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-sample +# +### +FROM quay.io/quarkus/quarkus-distroless-image:1.0 +COPY target/*-runner /application + +EXPOSE 8080 +USER nonroot + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/quarkus-jandex/hello-app/src/main/java/com/baeldung/quarkus/hello/HelloResource.java b/quarkus-jandex/hello-app/src/main/java/com/baeldung/quarkus/hello/HelloResource.java new file mode 100644 index 0000000000..1867527327 --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/java/com/baeldung/quarkus/hello/HelloResource.java @@ -0,0 +1,26 @@ +package com.baeldung.quarkus.hello; + +import com.baeldung.quarkus.hello.service.HelloService; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @Inject + HelloService service; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + StringBuilder sb = new StringBuilder(); + sb.append("Those are saying hello:\n=======================\n\n"); + service.sendHello(s -> sb.append(" - ").append(s).append("\n")); + return sb.toString(); + } + +} diff --git a/quarkus-jandex/hello-app/src/main/resources/META-INF/resources/index.html b/quarkus-jandex/hello-app/src/main/resources/META-INF/resources/index.html new file mode 100644 index 0000000000..ba625a1420 --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,14 @@ + + + + + qHello App + + + +

Hello App

+ +This app demonstrates how Quarkus resolves CDI managed beans. You can find the output of all resolved beans by invoking the Hello Resource. + + + diff --git a/quarkus-jandex/hello-app/src/main/resources/application.properties b/quarkus-jandex/hello-app/src/main/resources/application.properties new file mode 100644 index 0000000000..95ff9889c7 --- /dev/null +++ b/quarkus-jandex/hello-app/src/main/resources/application.properties @@ -0,0 +1,2 @@ +quarkus.index-dependency.hello-sender.group-id=com.baeldung.quarkus +quarkus.index-dependency.hello-sender.artifact-id=hello-sender-application-properties diff --git a/quarkus-jandex/hello-sender-application-properties/pom.xml b/quarkus-jandex/hello-sender-application-properties/pom.xml new file mode 100644 index 0000000000..f63bb9be81 --- /dev/null +++ b/quarkus-jandex/hello-sender-application-properties/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + hello-sender-application-properties + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-arc + + + ${project.groupId} + hello-service + ${project.version} + + + + diff --git a/quarkus-jandex/hello-sender-application-properties/src/main/java/com/baeldung/quarkus/hello/sender/applicationproperties/ApplicationPropertiesHelloSender.java b/quarkus-jandex/hello-sender-application-properties/src/main/java/com/baeldung/quarkus/hello/sender/applicationproperties/ApplicationPropertiesHelloSender.java new file mode 100644 index 0000000000..ffd495e92e --- /dev/null +++ b/quarkus-jandex/hello-sender-application-properties/src/main/java/com/baeldung/quarkus/hello/sender/applicationproperties/ApplicationPropertiesHelloSender.java @@ -0,0 +1,15 @@ +package com.baeldung.quarkus.hello.sender.applicationproperties; + +import com.baeldung.quarkus.hello.service.HelloRetrieving; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +@ApplicationScoped +public class ApplicationPropertiesHelloSender { + + public void sendHello(@Observes HelloRetrieving event) { + event.getHelloReceiver().accept("Hi, I was detected by inserting this module's groupId and artifactId into the app's application.properties file."); + } + +} diff --git a/quarkus-jandex/hello-sender-beans-xml/pom.xml b/quarkus-jandex/hello-sender-beans-xml/pom.xml new file mode 100644 index 0000000000..b302a41017 --- /dev/null +++ b/quarkus-jandex/hello-sender-beans-xml/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + hello-sender-beans-xml + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-arc + + + ${project.groupId} + hello-service + ${project.version} + + + + \ No newline at end of file diff --git a/quarkus-jandex/hello-sender-beans-xml/src/main/java/com/baeldung/quarkus/hello/sender/beansxml/BeansXmlHelloSender.java b/quarkus-jandex/hello-sender-beans-xml/src/main/java/com/baeldung/quarkus/hello/sender/beansxml/BeansXmlHelloSender.java new file mode 100644 index 0000000000..bed6a7793d --- /dev/null +++ b/quarkus-jandex/hello-sender-beans-xml/src/main/java/com/baeldung/quarkus/hello/sender/beansxml/BeansXmlHelloSender.java @@ -0,0 +1,15 @@ +package com.baeldung.quarkus.hello.sender.beansxml; + +import com.baeldung.quarkus.hello.service.HelloRetrieving; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +@ApplicationScoped +public class BeansXmlHelloSender { + + public void sendHello(@Observes HelloRetrieving event) { + event.getHelloReceiver().accept("Hi, I was detected using an empty META-INF/beans.xml file."); + } + +} diff --git a/book b/quarkus-jandex/hello-sender-beans-xml/src/main/resources/META-INF/beans.xml similarity index 100% rename from book rename to quarkus-jandex/hello-sender-beans-xml/src/main/resources/META-INF/beans.xml diff --git a/quarkus-jandex/hello-sender-maven-plugin/pom.xml b/quarkus-jandex/hello-sender-maven-plugin/pom.xml new file mode 100644 index 0000000000..215a00e479 --- /dev/null +++ b/quarkus-jandex/hello-sender-maven-plugin/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + hello-sender-maven-plugin + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-arc + + + ${project.groupId} + hello-service + ${project.version} + + + + + + + + org.jboss.jandex + jandex-maven-plugin + 1.2.1 + + + make-index + + + jandex + + + + + + + + \ No newline at end of file diff --git a/quarkus-jandex/hello-sender-maven-plugin/src/main/java/com/baeldung/quarkus/hello/sender/mavenplugin/MavenPluginHelloSender.java b/quarkus-jandex/hello-sender-maven-plugin/src/main/java/com/baeldung/quarkus/hello/sender/mavenplugin/MavenPluginHelloSender.java new file mode 100644 index 0000000000..ca08eef5ac --- /dev/null +++ b/quarkus-jandex/hello-sender-maven-plugin/src/main/java/com/baeldung/quarkus/hello/sender/mavenplugin/MavenPluginHelloSender.java @@ -0,0 +1,15 @@ +package com.baeldung.quarkus.hello.sender.mavenplugin; + +import com.baeldung.quarkus.hello.service.HelloRetrieving; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +@ApplicationScoped +public class MavenPluginHelloSender { + + public void sendHello(@Observes HelloRetrieving event) { + event.getHelloReceiver().accept("Hi, I was detected using the Jandex Maven Plugin."); + } + +} diff --git a/quarkus-jandex/hello-sender-undetected/pom.xml b/quarkus-jandex/hello-sender-undetected/pom.xml new file mode 100644 index 0000000000..2f9ca428b6 --- /dev/null +++ b/quarkus-jandex/hello-sender-undetected/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + hello-sender-undetected + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-arc + + + ${project.groupId} + hello-service + ${project.version} + + + + \ No newline at end of file diff --git a/quarkus-jandex/hello-sender-undetected/src/main/java/com/baeldung/quarkus/hello/sender/undetected/UndetectedHelloSender.java b/quarkus-jandex/hello-sender-undetected/src/main/java/com/baeldung/quarkus/hello/sender/undetected/UndetectedHelloSender.java new file mode 100644 index 0000000000..a39e610b2a --- /dev/null +++ b/quarkus-jandex/hello-sender-undetected/src/main/java/com/baeldung/quarkus/hello/sender/undetected/UndetectedHelloSender.java @@ -0,0 +1,15 @@ +package com.baeldung.quarkus.hello.sender.undetected; + +import com.baeldung.quarkus.hello.service.HelloRetrieving; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +@ApplicationScoped +public class UndetectedHelloSender { + + public void sendHello(@Observes HelloRetrieving event) { + event.getHelloReceiver().accept("Hi, I do not create a Jandex index, so I should not get detected."); + } + +} diff --git a/quarkus-jandex/hello-service/pom.xml b/quarkus-jandex/hello-service/pom.xml new file mode 100644 index 0000000000..065c3f4011 --- /dev/null +++ b/quarkus-jandex/hello-service/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + hello-service + + + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + + + + + io.quarkus + quarkus-arc + + + + \ No newline at end of file diff --git a/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloRetrieving.java b/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloRetrieving.java new file mode 100644 index 0000000000..513e2ff245 --- /dev/null +++ b/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloRetrieving.java @@ -0,0 +1,17 @@ +package com.baeldung.quarkus.hello.service; + +import java.util.function.Consumer; + +public class HelloRetrieving { + + private final Consumer helloReceiver; + + public HelloRetrieving(Consumer helloReceiver) { + this.helloReceiver = helloReceiver; + } + + public Consumer getHelloReceiver() { + return helloReceiver; + } + +} diff --git a/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloService.java b/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloService.java new file mode 100644 index 0000000000..4b93d2f12f --- /dev/null +++ b/quarkus-jandex/hello-service/src/main/java/com/baeldung/quarkus/hello/service/HelloService.java @@ -0,0 +1,18 @@ +package com.baeldung.quarkus.hello.service; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Event; +import javax.inject.Inject; +import java.util.function.Consumer; + +@ApplicationScoped +public class HelloService { + + @Inject + Event helloRetrievingEvent; + + public void sendHello(Consumer target) { + helloRetrievingEvent.fire(new HelloRetrieving(target)); + } + +} diff --git a/guest/core-java/src/test/resources/.keep b/quarkus-jandex/hello-service/src/main/resources/META-INF/beans.xml similarity index 100% rename from guest/core-java/src/test/resources/.keep rename to quarkus-jandex/hello-service/src/main/resources/META-INF/beans.xml diff --git a/quarkus-jandex/pom.xml b/quarkus-jandex/pom.xml new file mode 100644 index 0000000000..e3cdfa3835 --- /dev/null +++ b/quarkus-jandex/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + com.baeldung.quarkus + quarkus-jandex + 1.0.0-SNAPSHOT + pom + + + hello-service + hello-sender-beans-xml + hello-sender-maven-plugin + hello-sender-application-properties + hello-sender-undetected + hello-app + + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + 3.8.1 + true + 11 + 11 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 2.4.2.Final + 3.0.0-M5 + + + \ No newline at end of file diff --git a/quarkus-vs-springboot/pom.xml b/quarkus-vs-springboot/pom.xml index cf1cbb5d85..1726d076da 100644 --- a/quarkus-vs-springboot/pom.xml +++ b/quarkus-vs-springboot/pom.xml @@ -1,19 +1,19 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + quarkus-vs-springboot + 1.0-SNAPSHOT + quarkus-vs-springboot + pom + parent-modules com.baeldung 1.0.0-SNAPSHOT - 1.0-SNAPSHOT - quarkus-vs-springboot - quarkus-vs-springboot - pom - 4.0.0 - quarkus-project spring-project diff --git a/quarkus-vs-springboot/quarkus-project/.mvn/wrapper/maven-wrapper.properties b/quarkus-vs-springboot/quarkus-project/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..8c79a83ae4 --- /dev/null +++ b/quarkus-vs-springboot/quarkus-project/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/quarkus-vs-springboot/quarkus-project/mvnw b/quarkus-vs-springboot/quarkus-project/mvnw new file mode 100755 index 0000000000..5643201c7d --- /dev/null +++ b/quarkus-vs-springboot/quarkus-project/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/quarkus-vs-springboot/quarkus-project/mvnw.cmd b/quarkus-vs-springboot/quarkus-project/mvnw.cmd new file mode 100644 index 0000000000..23b7079a3d --- /dev/null +++ b/quarkus-vs-springboot/quarkus-project/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/quarkus-vs-springboot/quarkus-project/pom.xml b/quarkus-vs-springboot/quarkus-project/pom.xml index 58d547f3b0..eeeb9d3256 100644 --- a/quarkus-vs-springboot/quarkus-project/pom.xml +++ b/quarkus-vs-springboot/quarkus-project/pom.xml @@ -1,143 +1,150 @@ - - 4.0.0 - - com.baeldung - quarkus-vs-springboot - 1.0-SNAPSHOT - - quarkus-project - 0.1-SNAPSHOT - - 3.8.1 - true - 11 - 11 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 2.2.2.Final - 3.0.0-M4 - - + 4.0.0 + quarkus-project + 0.1-SNAPSHOT + + + com.baeldung + quarkus-vs-springboot + 1.0-SNAPSHOT + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + - - ${quarkus.platform.group-id} - ${quarkus.platform.artifact-id} - ${quarkus.platform.version} - pom - import - + + io.quarkus + quarkus-hibernate-reactive-panache + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.quarkus + quarkus-reactive-pg-client + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-container-image-docker + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + - - - - io.quarkus - quarkus-hibernate-reactive-panache - - - io.quarkus - quarkus-resteasy-reactive - - - io.quarkus - quarkus-resteasy-reactive-jackson - - - io.quarkus - quarkus-reactive-pg-client - - - io.quarkus - quarkus-arc - - - io.quarkus - quarkus-container-image-docker - - - io.quarkus - quarkus-junit5 - test - - - io.rest-assured - rest-assured - test - - - - - - ${quarkus.platform.group-id} - quarkus-maven-plugin - ${quarkus.platform.version} - true - - - - build - generate-code - generate-code-tests - - - - - - maven-compiler-plugin - ${compiler-plugin.version} - - ${maven.compiler.parameters} - - - - maven-surefire-plugin - ${surefire-plugin.version} - - false - - org.jboss.logmanager.LogManager - - - - - - - - native - - - native - - - + + - - maven-failsafe-plugin - ${surefire-plugin.version} - - - - integration-test - verify - + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} - - ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager - + ${maven.compiler.parameters} - - - + + + maven-surefire-plugin + ${surefire-plugin.version} + + false + + org.jboss.logmanager.LogManager + + + - - - -H:+AllowVMInspection - native - - - - +
+ + + native + + + native + + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + + + + + + + + + -H:+AllowVMInspection + native + + + + + + 3.8.1 + true + 11 + 11 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 2.2.2.Final + 3.0.0-M4 + + + \ No newline at end of file diff --git a/quarkus-vs-springboot/spring-project/.mvn/wrapper/maven-wrapper.properties b/quarkus-vs-springboot/spring-project/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..8c79a83ae4 --- /dev/null +++ b/quarkus-vs-springboot/spring-project/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/quarkus-vs-springboot/spring-project/mvnw b/quarkus-vs-springboot/spring-project/mvnw new file mode 100755 index 0000000000..5643201c7d --- /dev/null +++ b/quarkus-vs-springboot/spring-project/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/quarkus-vs-springboot/spring-project/mvnw.cmd b/quarkus-vs-springboot/spring-project/mvnw.cmd new file mode 100644 index 0000000000..23b7079a3d --- /dev/null +++ b/quarkus-vs-springboot/spring-project/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/quarkus-vs-springboot/spring-project/pom.xml b/quarkus-vs-springboot/spring-project/pom.xml index be5cc57765..bf524cd550 100644 --- a/quarkus-vs-springboot/spring-project/pom.xml +++ b/quarkus-vs-springboot/spring-project/pom.xml @@ -1,25 +1,18 @@ - - - org.springframework.boot - spring-boot-starter-parent - 2.5.4 - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-project com.baeldung 0.1-SNAPSHOT - - 11 - - 0.10.3 - + + org.springframework.boot + spring-boot-starter-parent + 2.6.0 + + @@ -103,6 +96,16 @@ false + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + +
@@ -113,6 +116,16 @@ false + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + @@ -161,11 +174,19 @@ org.apache.maven.plugins maven-surefire-plugin - -DspringAot=true -agentlib:native-image-agent=access-filter-file=src/test/resources/access-filter.json,config-merge-dir=target/classes/META-INF/native-image + -DspringAot=true + -agentlib:native-image-agent=access-filter-file=src/test/resources/access-filter.json,config-merge-dir=target/classes/META-INF/native-image + + + 11 + + 0.11.0-RC1 + + \ No newline at end of file diff --git a/quarkus-vs-springboot/spring-project/src/main/resources/application.properties b/quarkus-vs-springboot/spring-project/src/main/resources/application.properties index adc2f8b0b4..1d49b67fda 100644 --- a/quarkus-vs-springboot/spring-project/src/main/resources/application.properties +++ b/quarkus-vs-springboot/spring-project/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.r2dbc.url=${DB_URL:'r2dbc:postgresql://localhost:5432/postgres'} +spring.r2dbc.url=${DB_URL:r2dbc:postgresql://localhost:5432/postgres} spring.r2dbc.username=postgres spring.r2dbc.password=example spring.r2dbc.pool.enabled=true diff --git a/quarkus/pom.xml b/quarkus/pom.xml index d826729ad7..9342b1a4af 100644 --- a/quarkus/pom.xml +++ b/quarkus/pom.xml @@ -16,8 +16,8 @@ - + junit junit @@ -37,6 +37,12 @@ pom import + + org.mockito + mockito-core + ${mockito.version} + test + @@ -94,6 +100,11 @@ rest-assured test + + org.mockito + mockito-core + test + @@ -172,6 +183,7 @@ 1.7.0.Final 1.18.6 + 3.3.0 \ No newline at end of file diff --git a/reactor-core/README.md b/reactor-core/README.md index a4ced49096..7ca3b5773f 100644 --- a/reactor-core/README.md +++ b/reactor-core/README.md @@ -4,7 +4,6 @@ This module contains articles about Reactor Core. ### Relevant articles -- [Intro To Reactor Core](https://www.baeldung.com/reactor-core) - [Combining Publishers in Project Reactor](https://www.baeldung.com/reactor-combine-streams) - [Programmatically Creating Sequences with Project Reactor](https://www.baeldung.com/flux-sequences-reactor) - [How to Extract a Mono’s Content in Java](https://www.baeldung.com/java-string-from-mono) diff --git a/reactor-core/pom.xml b/reactor-core/pom.xml index 420b1b028a..39a66cee3e 100644 --- a/reactor-core/pom.xml +++ b/reactor-core/pom.xml @@ -26,12 +26,6 @@ ${reactor.version} test - - org.assertj - assertj-core - ${assertj.version} - test - org.projectlombok lombok @@ -42,7 +36,6 @@ 3.4.9 - 3.6.1 \ No newline at end of file diff --git a/reactor-core/src/main/resources/logback.xml b/reactor-core/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/reactor-core/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/restx/pom.xml b/restx/pom.xml index ea9f927563..953b56e2f3 100644 --- a/restx/pom.xml +++ b/restx/pom.xml @@ -113,12 +113,6 @@ - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - @@ -153,6 +147,7 @@ 0.35-rc4 + 1.6.0 \ No newline at end of file diff --git a/rule-engines/evrete/pom.xml b/rule-engines/evrete/pom.xml index 819a912c43..cfcadcb2ea 100644 --- a/rule-engines/evrete/pom.xml +++ b/rule-engines/evrete/pom.xml @@ -8,10 +8,6 @@ 1.0 evrete - - 2.1.04 - - com.baeldung rule-engines @@ -32,4 +28,9 @@ ${evrete.version} + + + 2.1.04 + + \ No newline at end of file diff --git a/rxjava-core/pom.xml b/rxjava-core/pom.xml index cd6075e127..89ea1bf7a2 100644 --- a/rxjava-core/pom.xml +++ b/rxjava-core/pom.xml @@ -30,15 +30,9 @@ awaitility ${awaitility.version} - - org.assertj - assertj-core - ${assertj.version} - - 3.8.0 1.2.5 1.7.0 2.2.2 diff --git a/rxjava-libraries/pom.xml b/rxjava-libraries/pom.xml index 5d2c9ec3bb..f8df78d741 100644 --- a/rxjava-libraries/pom.xml +++ b/rxjava-libraries/pom.xml @@ -41,11 +41,6 @@ ${h2.version} runtime - - org.assertj - assertj-core - ${assertj.version} - @@ -53,7 +48,6 @@ 1.2.5 2.0.0 2.2.2 - 3.8.0 \ No newline at end of file diff --git a/rxjava-observables/pom.xml b/rxjava-observables/pom.xml index feb4fc1f39..bcc3c4bbce 100644 --- a/rxjava-observables/pom.xml +++ b/rxjava-observables/pom.xml @@ -25,17 +25,11 @@ rxjava-string ${rx.java.string.version} - - org.assertj - assertj-core - ${assertj.version} - 1.1.1 1.2.5 - 3.8.0 \ No newline at end of file diff --git a/rxjava-operators/pom.xml b/rxjava-operators/pom.xml index ba85dc428b..d833fb5d14 100644 --- a/rxjava-operators/pom.xml +++ b/rxjava-operators/pom.xml @@ -31,11 +31,6 @@ rxjava2-extensions ${rxjava2.ext.version} - - org.assertj - assertj-core - ${assertj.version} - io.reactivex rxjava-math @@ -51,7 +46,6 @@ 0.20.4 2.2.2 - 3.8.0 1.2.5 1.0.0 1.7.0 diff --git a/software-security/sql-injection-samples/src/main/resources/logback.xml b/software-security/sql-injection-samples/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/software-security/sql-injection-samples/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/software-security/sql-injection-samples/src/test/resources/logback-test.xml b/software-security/sql-injection-samples/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spf4j/spf4j-aspects-app/pom.xml b/spf4j/spf4j-aspects-app/pom.xml index c4940b9c97..09ca41ea47 100644 --- a/spf4j/spf4j-aspects-app/pom.xml +++ b/spf4j/spf4j-aspects-app/pom.xml @@ -9,10 +9,9 @@ jar - com.baeldung - parent-modules + com.baeldung.spf4j + spf4j 1.0.0-SNAPSHOT - ../../ diff --git a/spf4j/spf4j-core-app/pom.xml b/spf4j/spf4j-core-app/pom.xml index 28c104afe1..2f7f3745f1 100644 --- a/spf4j/spf4j-core-app/pom.xml +++ b/spf4j/spf4j-core-app/pom.xml @@ -9,10 +9,9 @@ jar - com.baeldung - parent-modules + com.baeldung.spf4j + spf4j 1.0.0-SNAPSHOT - ../../ diff --git a/spring-4/pom.xml b/spring-4/pom.xml index 41f55ea13b..5887bd43e2 100644 --- a/spring-4/pom.xml +++ b/spring-4/pom.xml @@ -74,10 +74,12 @@ org.apache.logging.log4j log4j-api + ${log4j2.version} org.apache.logging.log4j log4j-core + ${log4j2.version} org.easymock @@ -115,6 +117,7 @@ 3.6 2.4.0 4.0.3 + 2.17.1 \ No newline at end of file diff --git a/spring-5-autowiring-beans/README.md b/spring-5-autowiring-beans/README.md new file mode 100644 index 0000000000..dc8751325e --- /dev/null +++ b/spring-5-autowiring-beans/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring @Autowired Field Null – Common Causes and Solutions](https://www.baeldung.com/spring-autowired-field-null) diff --git a/spring-5-autowiring-beans/pom.xml b/spring-5-autowiring-beans/pom.xml new file mode 100644 index 0000000000..32b56cc9ad --- /dev/null +++ b/spring-5-autowiring-beans/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + spring-5-autowiring-beans + 0.0.1-SNAPSHOT + spring-5-autowiring-beans + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + diff --git a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/App.java similarity index 56% rename from guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java rename to spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/App.java index 42d40fa02d..d2d0db7a60 100644 --- a/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/App.java @@ -1,15 +1,14 @@ -package com.stackify.guest.springmvc; +package com.baeldung.autowiring; +import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -import org.springframework.boot.SpringApplication; @SpringBootApplication -@ComponentScan(basePackages = {"com.stackify.guest.springmvc"}) -public class Spring5Application { +public class App { public static void main(String[] args) { - SpringApplication.run(Spring5Application.class, args); + SpringApplication.run(App.class, args); } } diff --git a/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/CorrectController.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/CorrectController.java new file mode 100644 index 0000000000..e0c0d7eeac --- /dev/null +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/CorrectController.java @@ -0,0 +1,18 @@ +package com.baeldung.autowiring.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +import com.baeldung.autowiring.service.MyService; + +@Controller +public class CorrectController { + + @Autowired + MyService myService; + + public String control() { + return myService.serve(); + } + +} diff --git a/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/FlawedController.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/FlawedController.java new file mode 100644 index 0000000000..673e686f79 --- /dev/null +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/controller/FlawedController.java @@ -0,0 +1,15 @@ +package com.baeldung.autowiring.controller; + +import org.springframework.stereotype.Controller; + +import com.baeldung.autowiring.service.MyService; + +@Controller +public class FlawedController { + + public String control() { + MyService userService = new MyService(); + return userService.serve(); + } + +} diff --git a/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyComponent.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyComponent.java new file mode 100644 index 0000000000..c04ca3f4ba --- /dev/null +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyComponent.java @@ -0,0 +1,10 @@ +package com.baeldung.autowiring.service; + +import org.springframework.stereotype.Component; + +@Component +public class MyComponent { + + public void doWork() {} + +} diff --git a/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyService.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyService.java new file mode 100644 index 0000000000..3443dc05de --- /dev/null +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyService.java @@ -0,0 +1,19 @@ +package com.baeldung.autowiring.service; + +import org.springframework.beans.factory.annotation.Autowired; + +/** + * The bean corresponding to this class is defined in MyServiceConfiguration + * Alternatively, you could choose to decorate this class with @Component or @Service + */ +public class MyService { + + @Autowired + MyComponent myComponent; + + public String serve() { + myComponent.doWork(); + return "success"; + } + +} diff --git a/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java new file mode 100644 index 0000000000..e30e4f770e --- /dev/null +++ b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java @@ -0,0 +1,14 @@ +package com.baeldung.autowiring.service; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyServiceConfiguration { + + @Bean + MyService myService() { + return new MyService(); + } + +} diff --git a/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java b/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java new file mode 100644 index 0000000000..3807641edd --- /dev/null +++ b/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java @@ -0,0 +1,23 @@ +package com.baeldung.autowiring.controller; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class CorrectControllerIntegrationTest { + + @Autowired + CorrectController controller; + + @Test + void whenControl_ThenRunSuccessfully() { + assertDoesNotThrow(() -> controller.control()); + } + +} diff --git a/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java b/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java new file mode 100644 index 0000000000..79d446604f --- /dev/null +++ b/spring-5-autowiring-beans/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.autowiring.controller; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class FlawedControllerIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FlawedControllerIntegrationTest.class); + + @Autowired + FlawedController myController; + + @Test + void whenControl_ThenThrowNullPointerException() { + NullPointerException npe = assertThrows(NullPointerException.class, () -> myController.control()); + LOGGER.error("Got a NullPointerException", npe); + } + +} diff --git a/spring-5-data-reactive/pom.xml b/spring-5-data-reactive/pom.xml index 3a9651de39..c145992737 100644 --- a/spring-5-data-reactive/pom.xml +++ b/spring-5-data-reactive/pom.xml @@ -72,7 +72,6 @@ com.h2database h2 - ${h2.version} org.apache.httpcomponents @@ -135,7 +134,6 @@ 1.0.0.RELEASE 0.8.1.RELEASE 4.5.2 - 1.4.200 1.5.23 3.3.1.RELEASE diff --git a/spring-5-reactive-2/README.md b/spring-5-reactive-2/README.md index 98a5f26433..1cd3bf46c6 100644 --- a/spring-5-reactive-2/README.md +++ b/spring-5-reactive-2/README.md @@ -1,13 +1,10 @@ ## Spring 5 Reactive Project -This module contains articles about reactive Spring 5 +This module contains articles about reactive Spring 5. -- [Spring WebClient vs. RestTemplate](https://www.baeldung.com/spring-webclient-resttemplate) - [Validation for Functional Endpoints in Spring 5](https://www.baeldung.com/spring-functional-endpoints-validation) -- [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging) - [Testing Reactive Streams Using StepVerifier and TestPublisher](https://www.baeldung.com/reactive-streams-step-verifier-test-publisher) -- [Debugging Reactive Streams in Java](https://www.baeldung.com/spring-debugging-reactive-streams) - [Static Content in Spring WebFlux](https://www.baeldung.com/spring-webflux-static-content) - [Server-Sent Events in Spring](https://www.baeldung.com/spring-server-sent-events) - [Backpressure Mechanism in Spring WebFlux](https://www.baeldung.com/spring-webflux-backpressure) -- More articles: [[<-- prev]](/spring-5-reactive) +- More articles: [[<-- prev]](../spring-5-reactive) [[next -->]](../spring-5-reactive-3) diff --git a/spring-5-reactive-2/pom.xml b/spring-5-reactive-2/pom.xml index 0758365932..627368aafb 100644 --- a/spring-5-reactive-2/pom.xml +++ b/spring-5-reactive-2/pom.xml @@ -75,6 +75,41 @@ + + + integration-lite-first + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + integration-lite-second + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + 1.0.1.RELEASE 2.24.0 diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java b/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java index e7cb60dbf9..a12d762fe5 100644 --- a/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java +++ b/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java @@ -1,21 +1,25 @@ package com.baeldung.backpressure; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import reactor.core.publisher.BaseSubscriber; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; public class BackpressureUnitTest { + private static final Logger LOGGER = LoggerFactory.getLogger(BackpressureUnitTest.class); + @Test public void whenLimitRateSet_thenSplitIntoChunks() throws InterruptedException { Flux limit = Flux.range(1, 25); limit.limitRate(10); limit.subscribe( - value -> System.out.println(value), + value -> LOGGER.debug(String.valueOf(value)), err -> err.printStackTrace(), - () -> System.out.println("Finished!!"), + () -> LOGGER.debug("Finished!!"), subscription -> subscription.request(15) ); @@ -34,12 +38,12 @@ public class BackpressureUnitTest { Flux request = Flux.range(1, 50); request.subscribe( - System.out::println, + integer -> LOGGER.debug(String.valueOf(integer)), err -> err.printStackTrace(), - () -> System.out.println("All 50 items have been successfully processed!!!"), + () -> LOGGER.debug("All 50 items have been successfully processed!!!"), subscription -> { for (int i = 0; i < 5; i++) { - System.out.println("Requesting the next 10 elements!!!"); + LOGGER.debug("Requesting the next 10 elements!!!"); subscription.request(10); } } @@ -68,7 +72,7 @@ public class BackpressureUnitTest { @Override protected void hookOnNext(Integer value) { request(3); - System.out.println(value); + LOGGER.debug(String.valueOf(value)); cancel(); } }); diff --git a/spring-5-reactive-2/src/test/resources/logback-test.xml b/spring-5-reactive-2/src/test/resources/logback-test.xml index 514029e402..6f1d947e93 100644 --- a/spring-5-reactive-2/src/test/resources/logback-test.xml +++ b/spring-5-reactive-2/src/test/resources/logback-test.xml @@ -1,16 +1,12 @@ - - - + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + - - - - - - + + + - \ No newline at end of file + \ No newline at end of file diff --git a/spring-5-reactive-3/.gitignore b/spring-5-reactive-3/.gitignore new file mode 100644 index 0000000000..dec013dfa4 --- /dev/null +++ b/spring-5-reactive-3/.gitignore @@ -0,0 +1,12 @@ +#folders# +.idea +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-5-reactive-3/README.md b/spring-5-reactive-3/README.md new file mode 100644 index 0000000000..da44bf98fc --- /dev/null +++ b/spring-5-reactive-3/README.md @@ -0,0 +1,6 @@ +## Spring 5 Reactive Project + +This module contains articles about reactive Spring 5. + +- [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging) +- More articles: [[<-- prev]](../spring-5-reactive-2) diff --git a/spring-5-reactive-3/pom.xml b/spring-5-reactive-3/pom.xml new file mode 100644 index 0000000000..89af34732f --- /dev/null +++ b/spring-5-reactive-3/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + spring-5-reactive-3 + 0.0.1-SNAPSHOT + spring-5-reactive-3 + jar + spring 5 sample project about new features + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.projectreactor + reactor-spring + ${reactor-spring.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + io.projectreactor + reactor-test + test + + + + + 1.0.1.RELEASE + + \ No newline at end of file diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/webflux/logging/WebFluxLoggingExample.java b/spring-5-reactive-3/src/main/java/com/baeldung/webflux/logging/WebFluxLoggingExample.java similarity index 100% rename from spring-5-reactive-2/src/main/java/com/baeldung/webflux/logging/WebFluxLoggingExample.java rename to spring-5-reactive-3/src/main/java/com/baeldung/webflux/logging/WebFluxLoggingExample.java diff --git a/spring-5-reactive-3/src/main/resources/application.properties b/spring-5-reactive-3/src/main/resources/application.properties new file mode 100644 index 0000000000..815cc2b76d --- /dev/null +++ b/spring-5-reactive-3/src/main/resources/application.properties @@ -0,0 +1 @@ +# application properties \ No newline at end of file diff --git a/spring-5-reactive-3/src/test/resources/logback-test.xml b/spring-5-reactive-3/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..25f2184c85 --- /dev/null +++ b/spring-5-reactive-3/src/test/resources/logback-test.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-5-reactive-client/README.md b/spring-5-reactive-client/README.md index e485897d27..5a93e0b13e 100644 --- a/spring-5-reactive-client/README.md +++ b/spring-5-reactive-client/README.md @@ -12,3 +12,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring WebClient Filters](https://www.baeldung.com/spring-webclient-filters) - [Get List of JSON Objects with WebClient](https://www.baeldung.com/spring-webclient-json-list) - [Upload a File with WebClient](https://www.baeldung.com/spring-webclient-upload-file) +- [How to Get Response Body When Testing the Status Code in WebFlux WebClient](https://www.baeldung.com/spring-webclient-get-response-body) diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 136f31b49e..7acc958a53 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -94,7 +94,7 @@ com.github.tomakehurst wiremock-standalone - 2.26.0 + ${wiremock-standalone.version} test @@ -110,13 +110,13 @@ org.mockito mockito-junit-jupiter - 2.23.0 + ${mockito.version} test io.projectreactor reactor-test - 3.2.10.RELEASE + ${reactor-test.version} test @@ -148,14 +148,50 @@ + + + integration-lite-first + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + integration-lite-second + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + 1.0.1.RELEASE 1.1.3 1.0 1.0 - 4.1 1.1.6 4.0.1 + 3.2.10.RELEASE + 2.26.0 \ No newline at end of file diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java new file mode 100644 index 0000000000..784fcf2812 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java @@ -0,0 +1,54 @@ +package com.baeldung.webclient.status; + +import com.baeldung.webclient.status.exception.CustomBadRequestException; +import com.baeldung.webclient.status.exception.CustomServerErrorException; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +public class WebClientStatusCodeHandler { + + public static Mono getResponseBodyUsingExchangeFilterFunction(String uri) { + ExchangeFilterFunction errorResponseFilter = ExchangeFilterFunction + .ofResponseProcessor(WebClientStatusCodeHandler::exchangeFilterResponseProcessor); + return WebClient + .builder() + .filter(errorResponseFilter) + .build() + .post() + .uri(uri) + .retrieve() + .bodyToMono(String.class); + } + + public static Mono getResponseBodyUsingOnStatus(String uri) { + return WebClient + .builder() + .build() + .post() + .uri(uri) + .retrieve() + .onStatus( + HttpStatus.INTERNAL_SERVER_ERROR::equals, + response -> response.bodyToMono(String.class).map(CustomServerErrorException::new)) + .onStatus( + HttpStatus.BAD_REQUEST::equals, + response -> response.bodyToMono(String.class).map(CustomBadRequestException::new)) + .bodyToMono(String.class); + } + + private static Mono exchangeFilterResponseProcessor(ClientResponse response) { + HttpStatus status = response.statusCode(); + if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { + return response.bodyToMono(String.class) + .flatMap(body -> Mono.error(new CustomServerErrorException(body))); + } + if (HttpStatus.BAD_REQUEST.equals(status)) { + return response.bodyToMono(String.class) + .flatMap(body -> Mono.error(new CustomBadRequestException(body))); + } + return Mono.just(response); + } +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomBadRequestException.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomBadRequestException.java new file mode 100644 index 0000000000..ddc814b2d4 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomBadRequestException.java @@ -0,0 +1,7 @@ +package com.baeldung.webclient.status.exception; + +public class CustomBadRequestException extends Exception { + public CustomBadRequestException(String message) { + super(message); + } +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomServerErrorException.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomServerErrorException.java new file mode 100644 index 0000000000..12adbc94e4 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/status/exception/CustomServerErrorException.java @@ -0,0 +1,7 @@ +package com.baeldung.webclient.status.exception; + +public class CustomServerErrorException extends Exception { + public CustomServerErrorException(String message) { + super(message); + } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/WebClientStatusCodeHandlerIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/WebClientStatusCodeHandlerIntegrationTest.java new file mode 100644 index 0000000000..e491baf97a --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/WebClientStatusCodeHandlerIntegrationTest.java @@ -0,0 +1,98 @@ +package com.baeldung.webclient; + +import com.baeldung.webclient.status.WebClientStatusCodeHandler; +import com.github.tomakehurst.wiremock.WireMockServer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Mono; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@RunWith(SpringRunner.class) +public class WebClientStatusCodeHandlerIntegrationTest { + private String baseUrl; + private WireMockServer wireMockServer; + + @Before + public void setUp() { + wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); + wireMockServer.start(); + configureFor("localhost", wireMockServer.port()); + baseUrl = format("http://localhost:%s", wireMockServer.port()); + } + + @After + public void tearDown() { + wireMockServer.stop(); + } + + @Test + public void whenResponseIs2XX_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() { + stubPostResponse("/success", 200, "success"); + + Mono responseStatusHandler = WebClientStatusCodeHandler + .getResponseBodyUsingOnStatus(baseUrl + "/success"); + + Mono responseExchangeFilter = WebClientStatusCodeHandler + .getResponseBodyUsingExchangeFilterFunction(baseUrl + "/success"); + + assertThat(responseStatusHandler.block()) + .isEqualTo(responseExchangeFilter.block()) + .isEqualTo("success"); + } + + @Test + public void whenResponseIs500_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() { + stubPostResponse("/server-error", 500, "Internal Server Error"); + + Mono responseStatusHandler = WebClientStatusCodeHandler + .getResponseBodyUsingOnStatus(baseUrl + "/server-error"); + + Mono responseExchangeFilter = WebClientStatusCodeHandler + .getResponseBodyUsingExchangeFilterFunction(baseUrl + "/server-error"); + + assertThatThrownBy(responseStatusHandler::block) + .isInstanceOf(Exception.class) + .hasMessageContaining("Internal Server Error"); + + assertThatThrownBy(responseExchangeFilter::block) + .isInstanceOf(Exception.class) + .hasMessageContaining("Internal Server Error"); + } + + @Test + public void whenResponseIs400_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() { + stubPostResponse("/client-error", 400, "Bad Request"); + + Mono responseStatusHandler = WebClientStatusCodeHandler + .getResponseBodyUsingOnStatus(baseUrl + "/client-error"); + + Mono responseExchangeFilter = WebClientStatusCodeHandler + .getResponseBodyUsingExchangeFilterFunction(baseUrl + "/client-error"); + + assertThatThrownBy(responseStatusHandler::block) + .isInstanceOf(Exception.class) + .hasMessageContaining("Bad Request"); + + assertThatThrownBy(responseExchangeFilter::block) + .isInstanceOf(Exception.class) + .hasMessageContaining("Bad Request"); + } + + private static void stubPostResponse(String url, int statusCode, String response) { + stubFor(post(urlEqualTo(url)).willReturn(aResponse() + .withStatus(statusCode) + .withBody(response))); + } +} \ No newline at end of file diff --git a/spring-5-reactive-security/README.md b/spring-5-reactive-security/README.md index 915f74cd78..37f999648c 100644 --- a/spring-5-reactive-security/README.md +++ b/spring-5-reactive-security/README.md @@ -8,8 +8,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles - [Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuators) -- [Spring Security 5 for Reactive Applications](https://www.baeldung.com/spring-security-5-reactive) -- [Guide to Spring 5 WebFlux](https://www.baeldung.com/spring-webflux) -- [Introduction to the Functional Web Framework in Spring 5](https://www.baeldung.com/spring-5-functional-web) - [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver) - [Spring Webflux and CORS](https://www.baeldung.com/spring-webflux-cors) diff --git a/spring-5-reactive-security/pom.xml b/spring-5-reactive-security/pom.xml index 267a683fa7..7b697c7b00 100644 --- a/spring-5-reactive-security/pom.xml +++ b/spring-5-reactive-security/pom.xml @@ -110,7 +110,7 @@ org.springframework.boot spring-boot-maven-plugin - com.baeldung.webflux.EmployeeSpringApplication + com.baeldung.reactive.actuator.Spring5ReactiveApplication JAR @@ -123,7 +123,6 @@ 1.1.3 1.0 1.0 - 4.1 3.1.6.RELEASE diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeRepository.java b/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeRepository.java deleted file mode 100644 index d7f618f178..0000000000 --- a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeRepository.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.webflux; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.stereotype.Repository; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -@Repository -public class EmployeeRepository { - - static Map employeeData; - - static Map employeeAccessData; - - static - { - employeeData = new HashMap<>(); - employeeData.put("1",new Employee("1","Employee 1")); - employeeData.put("2",new Employee("2","Employee 2")); - employeeData.put("3",new Employee("3","Employee 3")); - employeeData.put("4",new Employee("4","Employee 4")); - employeeData.put("5",new Employee("5","Employee 5")); - employeeData.put("6",new Employee("6","Employee 6")); - employeeData.put("7",new Employee("7","Employee 7")); - employeeData.put("8",new Employee("8","Employee 8")); - employeeData.put("9",new Employee("9","Employee 9")); - employeeData.put("10",new Employee("10","Employee 10")); - - employeeAccessData=new HashMap<>(); - employeeAccessData.put("1", "Employee 1 Access Key"); - employeeAccessData.put("2", "Employee 2 Access Key"); - employeeAccessData.put("3", "Employee 3 Access Key"); - employeeAccessData.put("4", "Employee 4 Access Key"); - employeeAccessData.put("5", "Employee 5 Access Key"); - employeeAccessData.put("6", "Employee 6 Access Key"); - employeeAccessData.put("7", "Employee 7 Access Key"); - employeeAccessData.put("8", "Employee 8 Access Key"); - employeeAccessData.put("9", "Employee 9 Access Key"); - employeeAccessData.put("10", "Employee 10 Access Key"); - } - - public Mono findEmployeeById(String id) - { - return Mono.just(employeeData.get(id)); - } - - public Flux findAllEmployees() - { - return Flux.fromIterable(employeeData.values()); - } - - public Mono updateEmployee(Employee employee) - { - Employee existingEmployee=employeeData.get(employee.getId()); - if(existingEmployee!=null) - { - existingEmployee.setName(employee.getName()); - } - return Mono.just(existingEmployee); - } -} diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/SpringContextTest.java b/spring-5-reactive-security/src/test/java/com/baeldung/SpringContextTest.java index b4f4118527..e6123de118 100644 --- a/spring-5-reactive-security/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-5-reactive-security/src/test/java/com/baeldung/SpringContextTest.java @@ -1,14 +1,13 @@ package com.baeldung; +import com.baeldung.reactive.actuator.Spring5ReactiveApplication; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.reactive.security.SpringSecurity5Application; - @RunWith(SpringRunner.class) -@SpringBootTest(classes = SpringSecurity5Application.class) +@SpringBootTest(classes = Spring5ReactiveApplication.class) public class SpringContextTest { @Test diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index 1945b7ea33..0f4756c53e 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -7,11 +7,9 @@ The "REST With Spring" Classes: https://bit.ly/restwithspring ### Relevant Articles -- [Spring 5 WebClient](https://www.baeldung.com/spring-5-webclient) - [Exploring the Spring 5 WebFlux URL Matching](https://www.baeldung.com/spring-5-mvc-url-matching) - [Reactive WebSockets with Spring 5](https://www.baeldung.com/spring-5-reactive-websockets) - [Spring Webflux Filters](https://www.baeldung.com/spring-webflux-filters) - [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header) -- [Handling Errors in Spring WebFlux](https://www.baeldung.com/spring-webflux-errors) - [A Guide to Spring Session Reactive Support: WebSession](https://www.baeldung.com/spring-session-reactive) - More articles: [[next -->]](/spring-5-reactive-2) diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index 408573198b..b9456c7181 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -153,7 +153,6 @@ 1.1.3 1.0 1.0 - 4.1 \ No newline at end of file diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java deleted file mode 100644 index 725fd931e1..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.web.reactive; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class Task { - - private final String name; - - private final int id; - - public Task(@JsonProperty("name") String name, @JsonProperty("id") int id) { - this.name = name; - this.id = id; - } - - public String getName() { - return this.name; - } - - public int getId() { - return this.id; - } - - @Override - public String toString() { - return "Task{" + "name='" + name + '\'' + ", id=" + id + '}'; - } -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java deleted file mode 100644 index aa9b81de4f..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.web.reactive.client; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; - -@SpringBootApplication(exclude = { ReactiveSecurityAutoConfiguration.class }) -public class WebClientApplication { - - public static void main(String[] args) { - SpringApplication.run(WebClientApplication.class, args); - } - -} diff --git a/spring-5-webflux-2/README.md b/spring-5-webflux-2/README.md new file mode 100644 index 0000000000..0222ddbaa4 --- /dev/null +++ b/spring-5-webflux-2/README.md @@ -0,0 +1,7 @@ +## Spring 5 WebFlux 2 + +This module contains articles about Spring 5 WebFlux + +## Relevant articles: + +- [Spring Webflux and @Cacheable Annotation](https://www.baeldung.com/spring-webflux-cacheable) \ No newline at end of file diff --git a/spring-5-webflux-2/pom.xml b/spring-5-webflux-2/pom.xml new file mode 100644 index 0000000000..68945138d4 --- /dev/null +++ b/spring-5-webflux-2/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + spring-5-webflux-2 + 1.0-SNAPSHOT + spring-5-webflux-2 + http://www.baeldung.com + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.jupiter + junit-jupiter + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.platform + junit-plaform-commons + + + + + io.projectreactor.addons + reactor-extra + ${reactor.version} + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + + + io.projectreactor + reactor-test + test + + + org.testcontainers + mongodb + ${testcontainers-mongodb.version} + test + + + com.squareup.okhttp3 + mockwebserver + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 3.4.5 + 2.9.2 + 1.16.2 + + + \ No newline at end of file diff --git a/spring-5-webflux-2/src/main/java/caching/Item.java b/spring-5-webflux-2/src/main/java/caching/Item.java new file mode 100644 index 0000000000..627eeef740 --- /dev/null +++ b/spring-5-webflux-2/src/main/java/caching/Item.java @@ -0,0 +1,50 @@ +package caching; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Item { + + @Id + private String _id; + private String name; + private double price; + + public Item(String name, double price) { + this.name = name; + this.price = price; + } + + public Item() { + } + + public String get_id() { + return _id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public String toString() { + return "Item{" + + "id='" + _id + '\'' + + ", name='" + name + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/spring-5-webflux-2/src/main/java/caching/ItemRepository.java b/spring-5-webflux-2/src/main/java/caching/ItemRepository.java new file mode 100644 index 0000000000..d69edaf5df --- /dev/null +++ b/spring-5-webflux-2/src/main/java/caching/ItemRepository.java @@ -0,0 +1,8 @@ +package caching; + +import org.springframework.data.mongodb.repository.ReactiveMongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ItemRepository extends ReactiveMongoRepository { +} diff --git a/spring-5-webflux-2/src/main/java/caching/ItemService.java b/spring-5-webflux-2/src/main/java/caching/ItemService.java new file mode 100644 index 0000000000..85d7005831 --- /dev/null +++ b/spring-5-webflux-2/src/main/java/caching/ItemService.java @@ -0,0 +1,42 @@ +package caching; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import reactor.cache.CacheMono; +import reactor.core.publisher.Mono; + +@Service +public class ItemService { + + private final ItemRepository repository; + private final LoadingCache cache; + + public ItemService(ItemRepository repository) { + this.repository = repository; + this.cache = Caffeine.newBuilder() + .build(this::getItem_withAddons); + } + + @Cacheable("items") + public Mono getItem(String id) { + return repository.findById(id); + } + + public Mono save(Item item) { + return repository.save(item); + } + + @Cacheable("items") + public Mono getItem_withCache(String id) { + return repository.findById(id).cache(); + } + + @Cacheable("items") + public Mono getItem_withAddons(String id) { + return CacheMono.lookup(cache.asMap(), id) + .onCacheMissResume(() -> repository.findById(id).cast(Object.class)).cast(Item.class); + } + +} diff --git a/spring-5-webflux-2/src/main/java/caching/SpringWebfluxCachingApplication.java b/spring-5-webflux-2/src/main/java/caching/SpringWebfluxCachingApplication.java new file mode 100644 index 0000000000..df648fe6a3 --- /dev/null +++ b/spring-5-webflux-2/src/main/java/caching/SpringWebfluxCachingApplication.java @@ -0,0 +1,16 @@ +package caching; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@SpringBootApplication +@EnableMongoRepositories +@EnableCaching +public class SpringWebfluxCachingApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringWebfluxCachingApplication.class, args); + } +} diff --git a/spring-5-webflux-2/src/main/resources/application-cache.properties b/spring-5-webflux-2/src/main/resources/application-cache.properties new file mode 100644 index 0000000000..23414da2dd --- /dev/null +++ b/spring-5-webflux-2/src/main/resources/application-cache.properties @@ -0,0 +1,2 @@ +logging.level.org.springframework.data.mongodb.core.ReactiveMongoTemplate=DEBUG +logging.level.org.springframework.cache=TRACE \ No newline at end of file diff --git a/spring-5-webflux-2/src/main/resources/logback.xml b/spring-5-webflux-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..48b68c6bf1 --- /dev/null +++ b/spring-5-webflux-2/src/main/resources/logback.xml @@ -0,0 +1,31 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + netty-access.log + + %msg%n + + + + + + + + + + + + + + + + diff --git a/spring-5-webflux-2/src/test/java/caching/MonoFluxResultCachingLiveTest.java b/spring-5-webflux-2/src/test/java/caching/MonoFluxResultCachingLiveTest.java new file mode 100644 index 0000000000..daf8367209 --- /dev/null +++ b/spring-5-webflux-2/src/test/java/caching/MonoFluxResultCachingLiveTest.java @@ -0,0 +1,95 @@ +package caching; + + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.utility.DockerImageName; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@ActiveProfiles("cache") +public class MonoFluxResultCachingLiveTest { + + + @Autowired + ItemService itemService; + + final static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10")); + + @DynamicPropertySource + static void mongoDbProperties(DynamicPropertyRegistry registry) { + mongoDBContainer.start(); + registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl); + } + +@Test +public void givenItem_whenGetItemIsCalled_thenMonoIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); +} + + @Test + public void givenItem_whenGetItemWithCacheIsCalled_thenMonoResultIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem_withCache(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem_withCache(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); + } + + @Test + public void givenItem_whenGetItemWithAddonsIsCalled_thenMonoResultIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem_withAddons(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem_withAddons(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); + } + +} diff --git a/spring-5-webflux-2/src/test/resources/logback-test.xml b/spring-5-webflux-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..12cedf5952 --- /dev/null +++ b/spring-5-webflux-2/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + + diff --git a/spring-5-webflux/README.md b/spring-5-webflux/README.md index bd667468fb..c0b600943e 100644 --- a/spring-5-webflux/README.md +++ b/spring-5-webflux/README.md @@ -6,7 +6,6 @@ This module contains articles about Spring 5 WebFlux - [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty) - [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404) -- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters) - [RSocket Using Spring Boot](https://www.baeldung.com/spring-boot-rsocket) - [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) - [Set a Timeout in Spring 5 Webflux WebClient](https://www.baeldung.com/spring-webflux-timeout) diff --git a/spring-5/README.md b/spring-5/README.md index 952daa40d2..018aa05db7 100644 --- a/spring-5/README.md +++ b/spring-5/README.md @@ -10,5 +10,4 @@ This module contains articles about Spring 5 - [Spring ResponseStatusException](https://www.baeldung.com/spring-response-status-exception) - [Spring Assert Statements](https://www.baeldung.com/spring-assert) - [Difference between \ vs \](https://www.baeldung.com/spring-contextannotation-contextcomponentscan) -- [Finding the Spring Version](https://www.baeldung.com/spring-find-version) - [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 5799f3bc8f..1ac696e7bd 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -142,7 +142,6 @@ 1.0 1.5.6 - 4.1 ${project.build.directory}/generated-snippets 4.0.3 diff --git a/spring-aop-2/README.md b/spring-aop-2/README.md new file mode 100644 index 0000000000..a9694ac236 --- /dev/null +++ b/spring-aop-2/README.md @@ -0,0 +1,10 @@ +## Spring AOP + +This module contains articles about Spring aspect oriented programming (AOP) + +### Relevant articles + +- [Spring Performance Logging](https://www.baeldung.com/spring-performance-logging) +- [When Does Java Throw UndeclaredThrowableException?](https://www.baeldung.com/java-undeclaredthrowableexception) +- [Get Advised Method Info in Spring AOP](https://www.baeldung.com/spring-aop-get-advised-method-info) +- More articles: [[<-- prev]](/spring-aop) \ No newline at end of file diff --git a/spring-aop-2/pom.xml b/spring-aop-2/pom.xml new file mode 100644 index 0000000000..76e4780e72 --- /dev/null +++ b/spring-aop-2/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + spring-aop-2 + spring-aop-2 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.aspectj + aspectjrt + + + org.aspectj + aspectjweaver + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-core + test + + + + + 1.11 + + + \ No newline at end of file diff --git a/guest/spring-boot-app/src/main/java/com/stackify/Application.java b/spring-aop-2/src/main/java/com/baeldung/Application.java similarity index 89% rename from guest/spring-boot-app/src/main/java/com/stackify/Application.java rename to spring-aop-2/src/main/java/com/baeldung/Application.java index de03fb6c81..c0490d50c6 100644 --- a/guest/spring-boot-app/src/main/java/com/stackify/Application.java +++ b/spring-aop-2/src/main/java/com/baeldung/Application.java @@ -1,13 +1,12 @@ -package com.stackify; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { - + public static void main(String[] args) { SpringApplication.run(Application.class, args); } - } diff --git a/spring-aop/src/main/java/com/baeldung/method/info/Account.java b/spring-aop-2/src/main/java/com/baeldung/method/info/Account.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/method/info/Account.java rename to spring-aop-2/src/main/java/com/baeldung/method/info/Account.java diff --git a/spring-aop/src/main/java/com/baeldung/method/info/AccountOperation.java b/spring-aop-2/src/main/java/com/baeldung/method/info/AccountOperation.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/method/info/AccountOperation.java rename to spring-aop-2/src/main/java/com/baeldung/method/info/AccountOperation.java diff --git a/spring-aop/src/main/java/com/baeldung/method/info/BankAccountAspect.java b/spring-aop-2/src/main/java/com/baeldung/method/info/BankAccountAspect.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/method/info/BankAccountAspect.java rename to spring-aop-2/src/main/java/com/baeldung/method/info/BankAccountAspect.java diff --git a/spring-aop/src/main/java/com/baeldung/method/info/BankAccountService.java b/spring-aop-2/src/main/java/com/baeldung/method/info/BankAccountService.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/method/info/BankAccountService.java rename to spring-aop-2/src/main/java/com/baeldung/method/info/BankAccountService.java diff --git a/spring-aop/src/main/java/com/baeldung/method/info/WithdrawLimitException.java b/spring-aop-2/src/main/java/com/baeldung/method/info/WithdrawLimitException.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/method/info/WithdrawLimitException.java rename to spring-aop-2/src/main/java/com/baeldung/method/info/WithdrawLimitException.java diff --git a/spring-aop/src/main/java/com/baeldung/performancemonitor/AopConfiguration.java b/spring-aop-2/src/main/java/com/baeldung/performancemonitor/AopConfiguration.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/performancemonitor/AopConfiguration.java rename to spring-aop-2/src/main/java/com/baeldung/performancemonitor/AopConfiguration.java diff --git a/spring-aop/src/main/java/com/baeldung/performancemonitor/MyPerformanceMonitorInterceptor.java b/spring-aop-2/src/main/java/com/baeldung/performancemonitor/MyPerformanceMonitorInterceptor.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/performancemonitor/MyPerformanceMonitorInterceptor.java rename to spring-aop-2/src/main/java/com/baeldung/performancemonitor/MyPerformanceMonitorInterceptor.java diff --git a/spring-aop/src/main/java/com/baeldung/performancemonitor/PerfomanceApp.java b/spring-aop-2/src/main/java/com/baeldung/performancemonitor/PerfomanceApp.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/performancemonitor/PerfomanceApp.java rename to spring-aop-2/src/main/java/com/baeldung/performancemonitor/PerfomanceApp.java diff --git a/spring-aop/src/main/java/com/baeldung/performancemonitor/Person.java b/spring-aop-2/src/main/java/com/baeldung/performancemonitor/Person.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/performancemonitor/Person.java rename to spring-aop-2/src/main/java/com/baeldung/performancemonitor/Person.java diff --git a/spring-aop/src/main/java/com/baeldung/performancemonitor/PersonService.java b/spring-aop-2/src/main/java/com/baeldung/performancemonitor/PersonService.java similarity index 100% rename from spring-aop/src/main/java/com/baeldung/performancemonitor/PersonService.java rename to spring-aop-2/src/main/java/com/baeldung/performancemonitor/PersonService.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/SomeCheckedException.java b/spring-aop-2/src/main/java/com/baeldung/undeclared/SomeCheckedException.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/SomeCheckedException.java rename to spring-aop-2/src/main/java/com/baeldung/undeclared/SomeCheckedException.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/ThrowUndeclared.java b/spring-aop-2/src/main/java/com/baeldung/undeclared/ThrowUndeclared.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/ThrowUndeclared.java rename to spring-aop-2/src/main/java/com/baeldung/undeclared/ThrowUndeclared.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredApplication.java b/spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredApplication.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredApplication.java rename to spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredApplication.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredAspect.java b/spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredAspect.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredAspect.java rename to spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredAspect.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredService.java b/spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredService.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredService.java rename to spring-aop-2/src/main/java/com/baeldung/undeclared/UndeclaredService.java diff --git a/spring-aop-2/src/main/resources/logback.xml b/spring-aop-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..4eaa556705 --- /dev/null +++ b/spring-aop-2/src/main/resources/logback.xml @@ -0,0 +1,23 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-aop-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-aop-2/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..13c1c162f1 --- /dev/null +++ b/spring-aop-2/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,15 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-aop/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java b/spring-aop-2/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java rename to spring-aop-2/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionIntegrationTest.java b/spring-aop-2/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionIntegrationTest.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionIntegrationTest.java rename to spring-aop-2/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionIntegrationTest.java diff --git a/spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionUnitTest.java b/spring-aop-2/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionUnitTest.java similarity index 100% rename from spring-aop/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionUnitTest.java rename to spring-aop-2/src/test/java/com/baeldung/undeclared/UndeclaredThrowableExceptionUnitTest.java diff --git a/spring-aop/README.md b/spring-aop/README.md index b49c2bd457..4ef8c35fde 100644 --- a/spring-aop/README.md +++ b/spring-aop/README.md @@ -6,11 +6,9 @@ This module contains articles about Spring aspect oriented programming (AOP) - [Implementing a Custom Spring AOP Annotation](https://www.baeldung.com/spring-aop-annotation) - [Intro to AspectJ](https://www.baeldung.com/aspectj) -- [Spring Performance Logging](https://www.baeldung.com/spring-performance-logging) - [Introduction to Spring AOP](https://www.baeldung.com/spring-aop) - [Introduction to Pointcut Expressions in Spring](https://www.baeldung.com/spring-aop-pointcut-tutorial) - [Introduction to Advice Types in Spring](https://www.baeldung.com/spring-aop-advice-tutorial) -- [When Does Java Throw UndeclaredThrowableException?](https://www.baeldung.com/java-undeclaredthrowableexception) -- [Get Advised Method Info in Spring AOP](https://www.baeldung.com/spring-aop-get-advised-method-info) - [Advise Methods on Annotated Classes With AspectJ](https://www.baeldung.com/aspectj-advise-methods) - [Joinpoint vs. ProceedingJoinPoint in AspectJ](https://www.baeldung.com/aspectj-joinpoint-proceedingjoinpoint) +- More articles: [[next -->]](/spring-aop-2) diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml index da981987fe..0d48c479ca 100644 --- a/spring-aop/pom.xml +++ b/spring-aop/pom.xml @@ -32,11 +32,6 @@ spring-boot-starter-test test - - org.mockito - mockito-core - test - @@ -65,6 +60,15 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/main/resources/logback.xml + + + diff --git a/spring-aop/src/main/resources/logback.xml b/spring-aop/src/main/resources/logback.xml index 84885fae62..fe4dfdee56 100644 --- a/spring-aop/src/main/resources/logback.xml +++ b/spring-aop/src/main/resources/logback.xml @@ -13,10 +13,6 @@ - - - - diff --git a/spring-batch-2/README.md b/spring-batch-2/README.md index 08bf1933db..9b5d59f0b9 100644 --- a/spring-batch-2/README.md +++ b/spring-batch-2/README.md @@ -1,3 +1,5 @@ ### Relevant Articles: - [Spring Boot With Spring Batch](https://www.baeldung.com/spring-boot-spring-batch) +- [How to Trigger and Stop a Scheduled Spring Batch Job](https://www.baeldung.com/spring-batch-start-stop-job) +- More articles [[<-- prev]](/spring-batch) diff --git a/spring-batch-2/pom.xml b/spring-batch-2/pom.xml index c429c272bd..12d31aca14 100644 --- a/spring-batch-2/pom.xml +++ b/spring-batch-2/pom.xml @@ -22,10 +22,8 @@ spring-boot-starter-batch - org.hsqldb - hsqldb - ${hsqldb.version} - runtime + com.h2database + h2 org.springframework.boot @@ -44,11 +42,17 @@ ${spring.batch.version} test + + org.awaitility + awaitility + ${awaitility.version} + test + 4.3.0 - 2.5.1 + 3.1.1 \ No newline at end of file diff --git a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java similarity index 69% rename from spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java rename to spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java index cff4e96c89..c830a41855 100644 --- a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java @@ -11,26 +11,20 @@ import org.springframework.batch.core.configuration.annotation.EnableBatchProces import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.SimpleJobLauncher; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.ScheduledMethodRunnable; -import javax.sql.DataSource; import java.util.Date; import java.util.IdentityHashMap; import java.util.List; @@ -58,13 +52,16 @@ public class SpringBatchScheduler { @Autowired private StepBuilderFactory stepBuilderFactory; + @Autowired + private JobLauncher jobLauncher; + @Scheduled(fixedRate = 2000) public void launchJob() throws Exception { Date date = new Date(); logger.debug("scheduler starts at " + date); if (enabled.get()) { - JobExecution jobExecution = jobLauncher().run(job(), new JobParametersBuilder().addDate("launchDate", date) - .toJobParameters()); + JobExecution jobExecution = jobLauncher.run(job(), new JobParametersBuilder().addDate("launchDate", date) + .toJobParameters()); batchRunCounter.incrementAndGet(); logger.debug("Batch job ends with status as " + jobExecution.getStatus()); } @@ -110,56 +107,33 @@ public class SpringBatchScheduler { @Bean public Job job() { - return jobBuilderFactory.get("job") - .start(readBooks()) - .build(); - } - - @Bean - public JobLauncher jobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); - jobLauncher.setJobRepository(jobRepository()); - jobLauncher.afterPropertiesSet(); - return jobLauncher; - } - - @Bean - public JobRepository jobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(dataSource()); - factory.setTransactionManager(new ResourcelessTransactionManager()); - return factory.getObject(); - } - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.sqlite.JDBC"); - dataSource.setUrl("jdbc:sqlite:repository.sqlite"); - return dataSource; + return jobBuilderFactory + .get("job") + .start(readBooks()) + .build(); } @Bean protected Step readBooks() { return stepBuilderFactory.get("readBooks") - . chunk(2) - .reader(reader()) - .writer(writer()) - .build(); + . chunk(2) + .reader(reader()) + .writer(writer()) + .build(); } @Bean public FlatFileItemReader reader() { return new FlatFileItemReaderBuilder().name("bookItemReader") - .resource(new ClassPathResource("books.csv")) - .delimited() - .names(new String[] { "id", "name" }) - .fieldSetMapper(new BeanWrapperFieldSetMapper() { - { - setTargetType(Book.class); - } - }) - .build(); + .resource(new ClassPathResource("books.csv")) + .delimited() + .names(new String[] { "id", "name" }) + .fieldSetMapper(new BeanWrapperFieldSetMapper() { + { + setTargetType(Book.class); + } + }) + .build(); } @Bean diff --git a/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java new file mode 100644 index 0000000000..349a359efb --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.batchscheduler; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBatchSchedulerApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBatchSchedulerApplication.class, args); + } + +} diff --git a/spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java similarity index 98% rename from spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java rename to spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java index 8ee986c729..7deedeb63e 100644 --- a/spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java @@ -3,7 +3,7 @@ package com.baeldung.batchscheduler.model; public class Book { private int id; private String name; - + public Book() {} public Book(int id, String name) { @@ -27,7 +27,7 @@ public class Book { public void setName(String name) { this.name = name; } - + public String toString() { return "Book [id=" + id + ", name=" + name + "]"; } diff --git a/spring-batch/src/main/resources/books.csv b/spring-batch-2/src/main/resources/books.csv similarity index 100% rename from spring-batch/src/main/resources/books.csv rename to spring-batch-2/src/main/resources/books.csv diff --git a/spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java similarity index 76% rename from spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java rename to spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java index 81877fbc39..61e5a1dd74 100644 --- a/spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java +++ b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java @@ -4,32 +4,40 @@ import com.baeldung.batchscheduler.SpringBatchScheduler; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import static org.awaitility.Awaitility.await; import static java.util.concurrent.TimeUnit.*; -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = SpringBatchScheduler.class) +@SpringBatchTest +@SpringBootTest +@DirtiesContext +@PropertySource("classpath:application.properties") +@RunWith(SpringRunner.class) public class SpringBatchSchedulerIntegrationTest { @Autowired private ApplicationContext context; @Test - public void stopJobsWhenSchedulerDisabled() throws Exception { + public void stopJobsWhenSchedulerDisabled() { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); schedulerBean.stop(); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } @Test @@ -37,24 +45,24 @@ public class SpringBatchSchedulerIntegrationTest { ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler"); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } @Test public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); schedulerBean.cancelFutureSchedulerTasks(); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } diff --git a/spring-batch/README.md b/spring-batch/README.md index 3a89459629..b87a2149a0 100644 --- a/spring-batch/README.md +++ b/spring-batch/README.md @@ -7,8 +7,8 @@ This module contains articles about Spring Batch - [Introduction to Spring Batch](https://www.baeldung.com/introduction-to-spring-batch) - [Spring Batch using Partitioner](https://www.baeldung.com/spring-batch-partitioner) - [Spring Batch – Tasklets vs Chunks](https://www.baeldung.com/spring-batch-tasklet-chunk) -- [How to Trigger and Stop a Scheduled Spring Batch Job](https://www.baeldung.com/spring-batch-start-stop-job) - [Configuring Skip Logic in Spring Batch](https://www.baeldung.com/spring-batch-skip-logic) - [Testing a Spring Batch Job](https://www.baeldung.com/spring-batch-testing-job) - [Configuring Retry Logic in Spring Batch](https://www.baeldung.com/spring-batch-retry-logic) - [Conditional Flow in Spring Batch](https://www.baeldung.com/spring-batch-conditional-flow) +- More articles [[next -->]](/spring-batch-2) diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index 9879a4777f..32126fec9b 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -82,12 +82,6 @@ hsqldb runtime - - org.awaitility - awaitility - ${awaitility.version} - test - @@ -97,7 +91,6 @@ 4.1 2.3.1 2.12.3 - 3.1.1 \ No newline at end of file diff --git a/spring-batch/repository.sqlite b/spring-batch/repository.sqlite index a2b87ffa00..b6a954554c 100644 Binary files a/spring-batch/repository.sqlite and b/spring-batch/repository.sqlite differ diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 9f179dd97f..fabd54aa92 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -19,9 +19,11 @@ spring-boot spring-boot-1 + spring-boot-2 spring-boot-admin spring-boot-angular spring-boot-annotations + spring-boot-annotations-2 spring-boot-artifacts spring-boot-artifacts-2 spring-boot-autoconfiguration @@ -34,7 +36,6 @@ spring-boot-deployment spring-boot-di spring-boot-disable-logging - spring-boot-camel spring-boot-ci-cd spring-boot-custom-starter @@ -46,10 +47,12 @@ spring-boot-groovy spring-boot-jasypt - spring-boot-keycloak + spring-boot-libraries spring-boot-libraries-2 + spring-boot-libraries-comparison spring-boot-logging-log4j2 + spring-boot-multiple-datasources spring-boot-mvc spring-boot-mvc-2 spring-boot-mvc-3 @@ -68,11 +71,12 @@ spring-boot-springdoc spring-boot-swagger spring-boot-swagger-jwt + spring-boot-swagger-keycloak spring-boot-testing + spring-boot-testing-2 spring-boot-vue spring-boot-actuator spring-boot-data-2 - spring-boot-react spring-boot-validation @@ -95,19 +99,4 @@ - - - org.junit.jupiter - junit-jupiter - - - org.junit.vintage - junit-vintage-engine - - - - - 2.22.2 - - - \ No newline at end of file + diff --git a/spring-boot-modules/spring-boot-1/README.md b/spring-boot-modules/spring-boot-1/README.md index a818f60fb5..8e5214c69a 100644 --- a/spring-boot-modules/spring-boot-1/README.md +++ b/spring-boot-modules/spring-boot-1/README.md @@ -4,3 +4,8 @@ This module contains articles about Spring Boot Actuator in Spring Boot version ## Relevant articles: - [Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuators) +- [A Quick Intro to the SpringBootServletInitializer](https://www.baeldung.com/spring-boot-servlet-initializer) +- [Spring Shutdown Callbacks](https://www.baeldung.com/spring-shutdown-callbacks) +- [Dynamic DTO Validation Config Retrieved from the Database](https://www.baeldung.com/spring-dynamic-dto-validation) + + diff --git a/spring-boot-modules/spring-boot-1/pom.xml b/spring-boot-modules/spring-boot-1/pom.xml index 9f91cc8f2e..594e6459a4 100644 --- a/spring-boot-modules/spring-boot-1/pom.xml +++ b/spring-boot-modules/spring-boot-1/pom.xml @@ -20,14 +20,36 @@ org.springframework.boot spring-boot-starter + + org.springframework.boot + spring-boot-starter-thymeleaf + org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-tomcat + org.springframework.boot spring-boot-starter-actuator + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + com.h2database + h2 + test + org.springframework.boot spring-boot-starter-test @@ -40,8 +62,13 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} + + 2.17.1 + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java similarity index 93% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java index 5b9ce1271e..0aa0f0ae0b 100644 --- a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java +++ b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/servletinitializer/WarInitializerApplication.java @@ -5,7 +5,7 @@ import java.time.LocalDateTime; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/ShutdownHookApplication.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/ShutdownHookApplication.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/ShutdownHookApplication.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/ShutdownHookApplication.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean1.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean1.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean1.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean1.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean2.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean2.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean2.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean2.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean3.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean3.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/beans/Bean3.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/beans/Bean3.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/config/ExampleServletContextListener.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/config/ExampleServletContextListener.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/config/ExampleServletContextListener.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/config/ExampleServletContextListener.java diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/config/ShutdownHookConfiguration.java b/spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/config/ShutdownHookConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/shutdownhooks/config/ShutdownHookConfiguration.java rename to spring-boot-modules/spring-boot-1/src/main/java/com/baeldung/shutdownhooks/config/ShutdownHookConfiguration.java diff --git a/spring-boot-modules/spring-boot-1/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-1/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-1/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/spring-boot-modules/spring-boot/src/test/java/com/baeldung/servletinitializer/WarInitializerApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-1/src/test/java/com/baeldung/servletinitializer/WarInitializerApplicationIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot/src/test/java/com/baeldung/servletinitializer/WarInitializerApplicationIntegrationTest.java rename to spring-boot-modules/spring-boot-1/src/test/java/com/baeldung/servletinitializer/WarInitializerApplicationIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-1/src/test/resources/application.properties b/spring-boot-modules/spring-boot-1/src/test/resources/application.properties new file mode 100644 index 0000000000..b14abfcc81 --- /dev/null +++ b/spring-boot-modules/spring-boot-1/src/test/resources/application.properties @@ -0,0 +1,20 @@ +spring.mail.host=localhost +spring.mail.port=8025 +spring.mail.properties.mail.smtp.auth=false + +# spring.datasource.x +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa + +# hibernate.X +spring.jpa.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.show_sql=true +spring.jpa.hibernate.hbm2ddl.auto=create-drop +spring.jpa.hibernate.cache.use_second_level_cache=true +spring.jpa.hibernate.cache.use_query_cache=true +spring.jpa.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory + +management.security.enabled=false \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-1/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-1/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-1/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-2/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot-modules/spring-boot-2/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..b901097f2d --- /dev/null +++ b/spring-boot-modules/spring-boot-2/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-boot-modules/spring-boot-2/.mvn/wrapper/maven-wrapper.properties b/spring-boot-modules/spring-boot-2/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..642d572ce9 --- /dev/null +++ b/spring-boot-modules/spring-boot-2/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-boot-modules/spring-boot-2/README.md b/spring-boot-modules/spring-boot-2/README.md new file mode 100644 index 0000000000..7ea97f80c5 --- /dev/null +++ b/spring-boot-modules/spring-boot-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Speed up Spring Boot Startup Time](https://www.baeldung.com/spring-boot-startup-speed) diff --git a/spring-boot-modules/spring-boot-keycloak/mvnw b/spring-boot-modules/spring-boot-2/mvnw old mode 100755 new mode 100644 similarity index 62% rename from spring-boot-modules/spring-boot-keycloak/mvnw rename to spring-boot-modules/spring-boot-2/mvnw index 5bf251c077..41c0f0c23d --- a/spring-boot-modules/spring-boot-keycloak/mvnw +++ b/spring-boot-modules/spring-boot-2/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script +# Maven Start Up Batch script # # Required ENV vars: # ------------------ @@ -108,13 +108,12 @@ if $cygwin ; then CLASSPATH=`cygpath --path --unix "$CLASSPATH"` fi -# For Migwn, ensure paths are in UNIX format before anything is touched +# For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then [ -n "$M2_HOME" ] && M2_HOME="`(cd "$M2_HOME"; pwd)`" [ -n "$JAVA_HOME" ] && JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? fi if [ -z "$JAVA_HOME" ]; then @@ -200,8 +199,89 @@ if [ -z "$BASE_DIR" ]; then exit 1; fi +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -echo $MAVEN_PROJECTBASEDIR +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java @@ -216,6 +296,11 @@ if $cygwin; then MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` fi +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain exec "$JAVACMD" \ diff --git a/spring-boot-modules/spring-boot-keycloak/mvnw.cmd b/spring-boot-modules/spring-boot-2/mvnw.cmd similarity index 73% rename from spring-boot-modules/spring-boot-keycloak/mvnw.cmd rename to spring-boot-modules/spring-boot-2/mvnw.cmd index 019bd74d76..86115719e5 100644 --- a/spring-boot-modules/spring-boot-keycloak/mvnw.cmd +++ b/spring-boot-modules/spring-boot-2/mvnw.cmd @@ -18,7 +18,7 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script +@REM Maven Start Up Batch script @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @@ -26,7 +26,7 @@ @REM Optional ENV vars @REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -35,7 +35,9 @@ @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' @echo off -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @REM set %HOME% to equivalent of $HOME @@ -115,10 +117,47 @@ for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do s :endReadAdditionalConfig SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" - set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end diff --git a/spring-boot-modules/spring-boot-2/pom.xml b/spring-boot-modules/spring-boot-2/pom.xml new file mode 100644 index 0000000000..08dc517fa0 --- /dev/null +++ b/spring-boot-modules/spring-boot-2/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + spring-boot-2 + jar + Module for Spring Boot version 2.x + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.springframework + spring-context-indexer + ${spring-core.version} + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + springStartupApp + com.baeldung.springStart.SpringStartApplication + + + + + repackage + + + + + + + + + 2.14.1 + 5.3.15 + 11 + 11 + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-2/src/main/java/com/baeldung/springStart/SpringStartApplication.java b/spring-boot-modules/spring-boot-2/src/main/java/com/baeldung/springStart/SpringStartApplication.java new file mode 100644 index 0000000000..f149a4c67e --- /dev/null +++ b/spring-boot-modules/spring-boot-2/src/main/java/com/baeldung/springStart/SpringStartApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.springStart; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.LogbackMetricsAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; + +@SpringBootApplication +//@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class, JvmMetricsAutoConfiguration.class, +// LogbackMetricsAutoConfiguration.class, MetricsAutoConfiguration.class}) +public class SpringStartApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringStartApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-2/src/main/resources/application.properties new file mode 100644 index 0000000000..4a5f46a7b1 --- /dev/null +++ b/spring-boot-modules/spring-boot-2/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.main.lazy-initialization=true +logging.level.org.springframework.boot.autoconfigure=DEBUG +spring.jmx.enabled=false \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-actuator/README.md b/spring-boot-modules/spring-boot-actuator/README.md index 9e2f30786f..ea43377ed2 100644 --- a/spring-boot-modules/spring-boot-actuator/README.md +++ b/spring-boot-modules/spring-boot-actuator/README.md @@ -11,3 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Custom Information in Spring Boot Info Endpoint](https://www.baeldung.com/spring-boot-info-actuator-custom) - [Health Indicators in Spring Boot](https://www.baeldung.com/spring-boot-health-indicators) - [How to Enable All Endpoints in Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuator-enable-endpoints) +- [Spring Boot Startup Actuator Endpoint](https://www.baeldung.com/spring-boot-actuator-startup) +- [Metrics for your Spring REST API](https://www.baeldung.com/spring-rest-api-metrics) diff --git a/spring-boot-modules/spring-boot-actuator/pom.xml b/spring-boot-modules/spring-boot-actuator/pom.xml index eaeb3b4ac7..1ccf436bbf 100644 --- a/spring-boot-modules/spring-boot-actuator/pom.xml +++ b/spring-boot-modules/spring-boot-actuator/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-actuator + 0.0.1-SNAPSHOT spring-boot-actuator This is simple boot application for Spring boot actuator test - 0.0.1-SNAPSHOT com.baeldung.spring-boot-modules @@ -23,6 +23,10 @@ org.springframework.boot spring-boot-starter-web + + org.apache.tomcat.embed + tomcat-embed-jasper + org.springframework.boot spring-boot-starter-data-jpa @@ -35,6 +39,16 @@ com.h2database h2 + + javax.servlet + javax.servlet-api + provided + + + javax.servlet + jstl + runtime + org.springframework.boot spring-boot-starter-test @@ -51,6 +65,10 @@ spring-security-test test + + org.awaitility + awaitility + diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/MetricsApplication.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/MetricsApplication.java new file mode 100644 index 0000000000..729b3c0b96 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/MetricsApplication.java @@ -0,0 +1,42 @@ +package com.baeldung.metrics; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.security.servlet.SecurityRequestMatchersManagementContextConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.context.request.RequestContextListener; + +import javax.servlet.ServletContext; + +@EnableScheduling +@ComponentScan("com.baeldung.metrics") +@SpringBootApplication +public class MetricsApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(MetricsApplication.class); + } + + @Override + public void onStartup(ServletContext sc) { + // Manages the lifecycle of the root application context + sc.addListener(new RequestContextListener()); + } + + public static void main(final String[] args) { + // only load properties for this application + System.setProperty("spring.config.location", "classpath:application-metrics.properties"); + SpringApplication.run(MetricsApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/WebConfig.java similarity index 81% rename from spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java rename to spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/WebConfig.java index e35acb0bf0..4c38e4dbad 100644 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/WebConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.spring; +package com.baeldung.metrics; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -10,14 +10,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration -@ComponentScan("com.baeldung.web") +@ComponentScan("com.baeldung.metrics") @EnableWebMvc public class WebConfig implements WebMvcConfigurer { - public WebConfig() { - super(); - } - @Bean public ViewResolver viewResolver() { final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); @@ -26,11 +22,10 @@ public class WebConfig implements WebMvcConfigurer { return viewResolver; } - // API @Override public void addViewControllers(final ViewControllerRegistry registry) { - registry.addViewController("/graph.html"); - registry.addViewController("/homepage.html"); + registry.addViewController("/metrics/graph.html"); + registry.addViewController("/metrics/homepage.html"); } } \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/controller/MetricsController.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/controller/MetricsController.java new file mode 100644 index 0000000000..e52ddd70f1 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/controller/MetricsController.java @@ -0,0 +1,41 @@ +package com.baeldung.metrics.controller; + +import com.baeldung.metrics.service.InMemoryMetricService; +import com.baeldung.metrics.service.MetricService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Map; + +@Controller +@RequestMapping(value = "/metrics") +@ResponseBody +public class MetricsController { + + @Autowired + private InMemoryMetricService metricService; + + // change the qualifier to use the in-memory implementation + @Autowired + @Qualifier("customActuatorMetricService") + private MetricService graphMetricService; + + @GetMapping(value = "/metric") + public Map> getMetric() { + return metricService.getFullMetric(); + } + + @GetMapping(value = "/status-metric") + public Map getStatusMetric() { + return metricService.getStatusMetric(); + } + + @GetMapping(value = "/metric-graph-data") + public Object[][] getMetricData() { + return graphMetricService.getGraphData(); + } +} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/filter/MetricFilter.java similarity index 64% rename from spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java rename to spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/filter/MetricFilter.java index dee63b226f..0f7579f060 100644 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/filter/MetricFilter.java @@ -1,4 +1,11 @@ -package com.baeldung.web.metric; +package com.baeldung.metrics.filter; + +import com.baeldung.metrics.service.CustomActuatorMetricService; +import com.baeldung.metrics.service.InMemoryMetricService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -9,24 +16,23 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.context.support.WebApplicationContextUtils; - @Component public class MetricFilter implements Filter { @Autowired - private IMetricService metricService; + private InMemoryMetricService metricService; @Autowired - private ICustomActuatorMetricService actMetricService; + private CustomActuatorMetricService actMetricService; @Override - public void init(final FilterConfig config) throws ServletException { + public void init(final FilterConfig config) { if (metricService == null || actMetricService == null) { - metricService = (IMetricService) WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()).getBean("metricService"); - actMetricService = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()).getBean(CustomActuatorMetricService.class); + WebApplicationContext appContext = WebApplicationContextUtils + .getRequiredWebApplicationContext(config.getServletContext()); + + metricService = appContext.getBean(InMemoryMetricService.class); + actMetricService = appContext.getBean(CustomActuatorMetricService.class); } } @@ -42,8 +48,4 @@ public class MetricFilter implements Filter { actMetricService.increaseCount(status); } - @Override - public void destroy() { - - } } diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/ActuatorMetricService.java similarity index 61% rename from spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java rename to spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/ActuatorMetricService.java index 8c26fa04a0..3eef265c02 100644 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/ActuatorMetricService.java @@ -1,32 +1,31 @@ -package com.baeldung.web.metric; +package com.baeldung.metrics.service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; - @Service -public class ActuatorMetricService implements IActuatorMetricService { +public class ActuatorMetricService implements MetricService { + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); @Autowired private MeterRegistry publicMetrics; - private final List> statusMetricsByMinute; + private final List> statusMetricsByMinute; private final List statusList; - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); public ActuatorMetricService() { - super(); - statusMetricsByMinute = new ArrayList>(); - statusList = new ArrayList(); + statusMetricsByMinute = new ArrayList<>(); + statusList = new ArrayList<>(); } @Override @@ -36,19 +35,19 @@ public class ActuatorMetricService implements IActuatorMetricService { final int rowCount = statusMetricsByMinute.size() + 1; final Object[][] result = new Object[rowCount][colCount]; result[0][0] = "Time"; - int j = 1; + int j = 1; for (final String status : statusList) { result[0][j] = status; j++; } for (int i = 1; i < rowCount; i++) { - result[i][0] = dateFormat.format(new Date(current.getTime() - (60000 * (rowCount - i)))); + result[i][0] = DATE_FORMAT.format(new Date(current.getTime() - (60000L * (rowCount - i)))); } List minuteOfStatuses; - List last = new ArrayList(); + List last = new ArrayList<>(); for (int i = 1; i < rowCount; i++) { minuteOfStatuses = statusMetricsByMinute.get(i - 1); @@ -64,11 +63,9 @@ public class ActuatorMetricService implements IActuatorMetricService { return result; } - // Non - API - - @Scheduled(fixedDelay = 60000) + @Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds:60000}") private void exportMetrics() { - final ArrayList lastMinuteStatuses = initializeStatuses(statusList.size()); + final List lastMinuteStatuses = initializeStatuses(statusList.size()); for (final Meter counterMetric : publicMetrics.getMeters()) { updateMetrics(counterMetric, lastMinuteStatuses); @@ -77,34 +74,32 @@ public class ActuatorMetricService implements IActuatorMetricService { statusMetricsByMinute.add(lastMinuteStatuses); } - private ArrayList initializeStatuses(final int size) { - final ArrayList counterList = new ArrayList(); + private List initializeStatuses(int size) { + List counterList = new ArrayList<>(); for (int i = 0; i < size; i++) { counterList.add(0); } return counterList; } - private void updateMetrics(final Meter counterMetric, final ArrayList statusCount) { - String status = ""; - int index = -1; - int oldCount = 0; + private void updateMetrics(Meter counterMetric, List statusCount) { - if (counterMetric.getId().getName().contains("counter.status.")) { - status = counterMetric.getId().getName().substring(15, 18); // example 404, 200 + String metricName = counterMetric.getId().getName(); + + if (metricName.contains("counter.status.")) { + // example 404, 200 + String status = metricName.substring(15, 18); appendStatusIfNotExist(status, statusCount); - index = statusList.indexOf(status); - oldCount = statusCount.get(index) == null ? 0 : statusCount.get(index); + int index = statusList.indexOf(status); + int oldCount = statusCount.get(index) == null ? 0 : statusCount.get(index); statusCount.set(index, (int)((Counter) counterMetric).count() + oldCount); } } - private void appendStatusIfNotExist(final String status, final ArrayList statusCount) { + private void appendStatusIfNotExist(String status, List statusCount) { if (!statusList.contains(status)) { statusList.add(status); statusCount.add(0); } } - - // -} \ No newline at end of file +} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/CustomActuatorMetricService.java similarity index 68% rename from spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java rename to spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/CustomActuatorMetricService.java index ee17825b7c..9b4ccaa875 100644 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/CustomActuatorMetricService.java @@ -1,40 +1,36 @@ -package com.baeldung.web.metric; +package com.baeldung.metrics.service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.search.Search; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.search.Search; - @Service -public class CustomActuatorMetricService implements ICustomActuatorMetricService { +public class CustomActuatorMetricService implements MetricService { + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); @Autowired private MeterRegistry registry; - private final List> statusMetricsByMinute; + private final List> statusMetricsByMinute; private final List statusList; - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); public CustomActuatorMetricService() { - super(); - statusMetricsByMinute = new ArrayList>(); - statusList = new ArrayList(); + statusMetricsByMinute = new ArrayList<>(); + statusList = new ArrayList<>(); } - // API - - @Override - public void increaseCount(final int status) { + public void increaseCount(int status) { String counterName = "counter.status." + status; - registry.counter(counterName).increment(1); + registry.counter(counterName).increment(); if (!statusList.contains(counterName)) { statusList.add(counterName); } @@ -55,7 +51,7 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService } for (int i = 1; i < rowCount; i++) { - result[i][0] = dateFormat.format(new Date(current.getTime() - (60000 * (rowCount - i)))); + result[i][0] = DATE_FORMAT.format(new Date(current.getTime() - (60000L * (rowCount - i)))); } List minuteOfStatuses; @@ -72,19 +68,17 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService return result; } - // Non - API - - @Scheduled(fixedDelay = 60000) + @Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds:60000}") private void exportMetrics() { - final ArrayList statusCount = new ArrayList(); + List statusCount = new ArrayList<>(); for (final String status : statusList) { Search search = registry.find(status); - if (search != null) { - Counter counter = search.counter(); - statusCount.add(counter != null ? ((int) counter.count()) : 0); - registry.remove(counter); - } else { + Counter counter = search.counter(); + if (counter == null) { statusCount.add(0); + } else { + statusCount.add((int) counter.count()); + registry.remove(counter); } } statusMetricsByMinute.add(statusCount); diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/InMemoryMetricService.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/InMemoryMetricService.java new file mode 100644 index 0000000000..0be5c21727 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/InMemoryMetricService.java @@ -0,0 +1,112 @@ +package com.baeldung.metrics.service; + +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +@Service +public class InMemoryMetricService implements MetricService { + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + private final Map> metricMap; + private final Map statusMetric; + private final Map> timeMap; + + public InMemoryMetricService() { + metricMap = new ConcurrentHashMap<>(); + statusMetric = new ConcurrentHashMap<>(); + timeMap = new ConcurrentHashMap<>(); + } + + public void increaseCount(String request, int status) { + increaseMainMetric(request, status); + increaseStatusMetric(status); + updateTimeMap(status); + } + + public Map> getFullMetric() { + return metricMap; + } + + public Map getStatusMetric() { + return statusMetric; + } + + public Object[][] getGraphData() { + final int colCount = statusMetric.keySet().size() + 1; + final Set allStatus = statusMetric.keySet(); + final int rowCount = timeMap.keySet().size() + 1; + + final Object[][] result = new Object[rowCount][colCount]; + result[0][0] = "Time"; + + int j = 1; + for (final int status : allStatus) { + result[0][j] = status; + j++; + } + int i = 1; + Map tempMap; + for (final Entry> entry : timeMap.entrySet()) { + result[i][0] = entry.getKey(); + tempMap = entry.getValue(); + for (j = 1; j < colCount; j++) { + result[i][j] = tempMap.get((Integer) result[0][j]); + if (result[i][j] == null) { + result[i][j] = 0; + } + } + i++; + } + + for (int k = 1; k < result[0].length; k++) { + result[0][k] = result[0][k].toString(); + } + + return result; + } + + private void increaseMainMetric(String request, int status) { + Map statusMap = metricMap.get(request); + if (statusMap == null) { + statusMap = new ConcurrentHashMap<>(); + } + + Integer count = statusMap.get(status); + if (count == null) { + count = 1; + } else { + count++; + } + statusMap.put(status, count); + metricMap.put(request, statusMap); + } + + private void increaseStatusMetric(int status) { + statusMetric.merge(status, 1, Integer::sum); + } + + private void updateTimeMap(int status) { + final String time = DATE_FORMAT.format(new Date()); + Map statusMap = timeMap.get(time); + if (statusMap == null) { + statusMap = new ConcurrentHashMap<>(); + } + + Integer count = statusMap.get(status); + if (count == null) { + count = 1; + } else { + count++; + } + statusMap.put(status, count); + timeMap.put(time, statusMap); + } + +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/MetricService.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/MetricService.java new file mode 100644 index 0000000000..3642102b67 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/metrics/service/MetricService.java @@ -0,0 +1,7 @@ +package com.baeldung.metrics.service; + +public interface MetricService { + + Object[][] getGraphData(); + +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/ResourceInitializer.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/ResourceInitializer.java new file mode 100644 index 0000000000..e50816821c --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/ResourceInitializer.java @@ -0,0 +1,17 @@ +package com.baeldung.startup; + +import org.springframework.stereotype.Component; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@Component +public class ResourceInitializer { + + ResourceInitializer() throws Exception { + // simulate resource init with random delay of a few seconds + int randomDelay = ThreadLocalRandom.current().nextInt(5, 9); + TimeUnit.SECONDS.sleep(randomDelay); + } + +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/StartupTrackingApplication.java b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/StartupTrackingApplication.java new file mode 100644 index 0000000000..a3762cb98e --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/java/com/baeldung/startup/StartupTrackingApplication.java @@ -0,0 +1,38 @@ +package com.baeldung.startup; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; + +import static java.lang.Boolean.FALSE; + +@SpringBootApplication(exclude = { + SecurityAutoConfiguration.class, + ManagementWebSecurityAutoConfiguration.class} +) +public class StartupTrackingApplication { + + public static void main(String[] args) { + // only load properties for this application + System.setProperty("spring.config.location", "classpath:application-startup.properties"); + + SpringApplication app = new SpringApplication(StartupTrackingApplication.class); + BufferingApplicationStartup startup = new BufferingApplicationStartup(2048); + + if (shouldFilterSteps()) { + startup.addFilter(startupStep -> startupStep.getName().matches("spring.beans.instantiate")); + } + + app.setApplicationStartup(startup); + app.run(args); + } + + private static boolean shouldFilterSteps() { + return Boolean.parseBoolean( + System.getProperty("startup.steps.filter", FALSE.toString()) + ); + } + +} diff --git a/spring-boot-modules/spring-boot-actuator/src/main/resources/application-metrics.properties b/spring-boot-modules/spring-boot-actuator/src/main/resources/application-metrics.properties new file mode 100644 index 0000000000..5f753a0c62 --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/resources/application-metrics.properties @@ -0,0 +1,9 @@ +management.endpoints.web.exposure.include=info,health,metrics + +# JPA and Security is not required for Metrics application +spring.autoconfigure.exclude= org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, \ + org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, \ + org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, \ + org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, \ + org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration, \ + org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration diff --git a/spring-boot-modules/spring-boot-actuator/src/main/resources/application-startup.properties b/spring-boot-modules/spring-boot-actuator/src/main/resources/application-startup.properties new file mode 100644 index 0000000000..4cb5f2a94d --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/main/resources/application-startup.properties @@ -0,0 +1,6 @@ +management.endpoints.web.exposure.include=startup + +# JPA is not required for startup actuator endpoint +spring.autoconfigure.exclude= org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, \ + org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, \ + org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration diff --git a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/api-servlet.xml similarity index 100% rename from spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml rename to spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/api-servlet.xml diff --git a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/view/metrics/graph.jsp similarity index 93% rename from spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp rename to spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/view/metrics/graph.jsp index e1d5fdc987..75976557a0 100644 --- a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp +++ b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/view/metrics/graph.jsp @@ -11,7 +11,7 @@ }); function drawChart() { - $.get("", + $.get("", function(mydata) { var data = google.visualization.arrayToDataTable(mydata); diff --git a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/view/metrics/homepage.jsp similarity index 100% rename from spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp rename to spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/view/metrics/homepage.jsp diff --git a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/web.xml b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/web.xml similarity index 91% rename from spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/web.xml rename to spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/web.xml index 7129b6b4af..84566ba93d 100644 --- a/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/web.xml +++ b/spring-boot-modules/spring-boot-actuator/src/main/webapp/WEB-INF/web.xml @@ -16,7 +16,7 @@ contextConfigLocation - com.baeldung.spring + com.baeldung.metrics @@ -37,7 +37,7 @@ metricFilter - com.baeldung.web.metric.MetricFilter + com.baeldung.metrics.filter.MetricFilter diff --git a/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/metrics/MetricsApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/metrics/MetricsApplicationIntegrationTest.java new file mode 100644 index 0000000000..c83d4625dc --- /dev/null +++ b/spring-boot-modules/spring-boot-actuator/src/test/java/com/baeldung/metrics/MetricsApplicationIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.metrics; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.test.context.ActiveProfiles; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@SpringBootTest( + classes = MetricsApplication.class, + webEnvironment = RANDOM_PORT, + properties = {"fixedDelay.in.milliseconds=2000"} +) +@ActiveProfiles("metrics") +class MetricsApplicationIntegrationTest { + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void givenStatuses_WhenScheduledMethodExecuted_ExpectCountsAreAggregated() { + restTemplate.getForObject("/metrics/metric/notFound", String.class); + restTemplate.getForObject("/metrics/metric", String.class); + + await().untilAsserted(() -> { + Object[][] statusCounts = restTemplate.getForObject("/metrics/metric-graph-data", Object[][].class); + + assertThat(statusCounts[0]).contains("counter.status.200", "counter.status.404"); + + List requestCounts = getRequestCounts(statusCounts); + verify404RequestFrom(requestCounts); + verify200RequestsFrom(requestCounts); + }); + } + + private static void verify200RequestsFrom(List requestCounts) { + assertThat(requestCounts.size()).isGreaterThan(1); + } + + private static void verify404RequestFrom(List requestCounts) { + assertThat(requestCounts).contains(1); + } + + private static List getRequestCounts(Object[][] statusCounts) { + List requestCounts = new ArrayList<>(); + for (int i = 1; i < statusCounts.length; i++) { + for (int j = 1; j < statusCounts[i].length; j++) { + Integer count = (Integer) statusCounts[i][j]; + if (count >= 1) { + requestCounts.add(count); + } + } + } + return requestCounts; + } + +} diff --git a/spring-boot-modules/spring-boot-admin/pom.xml b/spring-boot-modules/spring-boot-admin/pom.xml index b995b6f02e..02d0faa5cd 100644 --- a/spring-boot-modules/spring-boot-admin/pom.xml +++ b/spring-boot-modules/spring-boot-admin/pom.xml @@ -5,14 +5,13 @@ 4.0.0 spring-boot-admin 0.0.1-SNAPSHOT - pom spring-boot-admin + pom com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml index eca92ff3a5..8a37980550 100644 --- a/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml +++ b/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-admin-client 0.0.1-SNAPSHOT - jar spring-boot-admin-client + jar Spring Boot Admin Client com.baeldung.spring-boot-modules spring-boot-admin 0.0.1-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml index a1daa3fa19..18ab6a8ead 100644 --- a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-admin-server 0.0.1-SNAPSHOT - jar spring-boot-admin-server + jar Spring Boot Admin Server com.baeldung.spring-boot-modules spring-boot-admin 0.0.1-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-angular/pom.xml b/spring-boot-modules/spring-boot-angular/pom.xml index 89a8814d2f..9c073f6fe0 100644 --- a/spring-boot-modules/spring-boot-angular/pom.xml +++ b/spring-boot-modules/spring-boot-angular/pom.xml @@ -6,14 +6,13 @@ com.baeldung.springbootangular spring-boot-angular 1.0 - jar spring-boot-angular + jar com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -32,7 +31,6 @@ com.h2database h2 - ${h2.version} runtime diff --git a/spring-boot-modules/spring-boot-annotations-2/README.md b/spring-boot-modules/spring-boot-annotations-2/README.md new file mode 100644 index 0000000000..ec72620b37 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations-2/README.md @@ -0,0 +1,9 @@ +## Spring Boot Annotations + +This module contains articles about Spring Boot annotations + +### Relevant Articles: + +- [Spring Conditional Annotations](https://www.baeldung.com/spring-conditional-annotations) +- [Guide to @SpringBootConfiguration in Spring Boot](https://www.baeldung.com/springbootconfiguration-annotation) +- More articles: [[<-- prev]](/spring-boot-modules/spring-boot-annotations) diff --git a/spring-boot-modules/spring-boot-annotations-2/pom.xml b/spring-boot-modules/spring-boot-annotations-2/pom.xml new file mode 100644 index 0000000000..99d1c4587b --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations-2/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + spring-boot-annotations-2 + spring-boot-annotations-2 + war + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-autoconfigure + + + + org.mockito + mockito-inline + test + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/LoggingService.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/LoggingService.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/annotations/conditional/LoggingService.java diff --git a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/Application.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/Application.java similarity index 100% rename from spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/Application.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/Application.java diff --git a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/PersonService.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/PersonService.java similarity index 100% rename from spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/PersonService.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/PersonService.java diff --git a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/PersonServiceImpl.java b/spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/PersonServiceImpl.java similarity index 100% rename from spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/springbootconfiguration/PersonServiceImpl.java rename to spring-boot-modules/spring-boot-annotations-2/src/main/java/com/baeldung/springbootconfiguration/PersonServiceImpl.java diff --git a/spring-boot-modules/spring-boot-annotations-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-annotations-2/src/main/resources/application.properties new file mode 100644 index 0000000000..ba17f62cd0 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations-2/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.main.web-application-type=none \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java rename to spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/springbootconfiguration/SpringContextTest.java b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/springbootconfiguration/SpringContextTest.java new file mode 100644 index 0000000000..11bbad8bb2 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations-2/src/test/java/com/baeldung/springbootconfiguration/SpringContextTest.java @@ -0,0 +1,15 @@ +package com.baeldung.springbootconfiguration; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringContextTest { + + @Test + public void contextLoads() { + } +} diff --git a/spring-boot-modules/spring-boot-annotations/README.md b/spring-boot-modules/spring-boot-annotations/README.md index 9742661f30..34d0283b48 100644 --- a/spring-boot-modules/spring-boot-annotations/README.md +++ b/spring-boot-modules/spring-boot-annotations/README.md @@ -11,4 +11,4 @@ This module contains articles about Spring Boot annotations - [Spring Bean Annotations](https://www.baeldung.com/spring-bean-annotations) - [Difference Between @ComponentScan and @EnableAutoConfiguration in Spring Boot](https://www.baeldung.com/spring-componentscan-vs-enableautoconfiguration) - [Where Should the Spring @Service Annotation Be Kept?](https://www.baeldung.com/spring-service-annotation-placement) -- [Spring Conditional Annotations](https://www.baeldung.com/spring-conditional-annotations) +- More articles: [[next -->]](/spring-boot-modules/spring-boot-annotations-2) diff --git a/spring-boot-modules/spring-boot-annotations/pom.xml b/spring-boot-modules/spring-boot-annotations/pom.xml index 22572e7492..91f2614de8 100644 --- a/spring-boot-modules/spring-boot-annotations/pom.xml +++ b/spring-boot-modules/spring-boot-annotations/pom.xml @@ -4,14 +4,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-annotations - war spring-boot-annotations + war com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-annotations/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-annotations/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/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/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/EmployeeApplicationUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/EmployeeApplicationUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/EmployeeApplicationUnitTest.java rename to spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/EmployeeApplicationUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/AuthApplicationUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/AuthApplicationUnitTest.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/AuthApplicationUnitTest.java rename to spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/AuthApplicationUnitTest.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/AbstractsAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/AbstractsAnnotatedTestConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/AbstractsAnnotatedTestConfiguration.java rename to spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/AbstractsAnnotatedTestConfiguration.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java rename to spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/InterfacesAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/InterfacesAnnotatedTestConfiguration.java similarity index 100% rename from spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/InterfacesAnnotatedTestConfiguration.java rename to spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/service/config/InterfacesAnnotatedTestConfiguration.java diff --git a/spring-boot-modules/spring-boot-artifacts-2/README.md b/spring-boot-modules/spring-boot-artifacts-2/README.md index 35f9cfab32..5d0a6ebcd1 100644 --- a/spring-boot-modules/spring-boot-artifacts-2/README.md +++ b/spring-boot-modules/spring-boot-artifacts-2/README.md @@ -5,3 +5,5 @@ This module contains articles about configuring the Spring Boot build process 2. ### Relevant Articles: - [Difference Between spring-boot:repackage and Maven package](https://www.baeldung.com/spring-boot-repackage-vs-mvn-package) +- [Intro to Spring Boot Starters](https://www.baeldung.com/spring-boot-starters) +- More articles: [[<-- prev]](/spring-boot-modules/spring-boot-artifacts) diff --git a/spring-boot-modules/spring-boot-artifacts-2/pom.xml b/spring-boot-modules/spring-boot-artifacts-2/pom.xml index 8cf78b79e0..d0e12caa53 100644 --- a/spring-boot-modules/spring-boot-artifacts-2/pom.xml +++ b/spring-boot-modules/spring-boot-artifacts-2/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-artifacts-2 - jar spring-boot-artifacts-2 + jar Demo project for Spring Boot com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-artifacts/README.md b/spring-boot-modules/spring-boot-artifacts/README.md index cb77cfad4d..ffe044c51b 100644 --- a/spring-boot-modules/spring-boot-artifacts/README.md +++ b/spring-boot-modules/spring-boot-artifacts/README.md @@ -5,9 +5,9 @@ This module contains articles about configuring the Spring Boot build process. ### Relevant Articles: - [Spring Boot Dependency Management with a Custom Parent](https://www.baeldung.com/spring-boot-dependency-management-custom-parent) - [Create a Fat Jar App with Spring Boot](https://www.baeldung.com/deployable-fat-jar-spring-boot) - - [Intro to Spring Boot Starters](https://www.baeldung.com/spring-boot-starters) - [Introduction to WebJars](https://www.baeldung.com/maven-webjars) - [A Quick Guide to Maven Wrapper](https://www.baeldung.com/maven-wrapper) - [Running a Spring Boot App with Maven vs an Executable War/Jar](https://www.baeldung.com/spring-boot-run-maven-vs-executable-jar) - [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) + - More articles: [[next -->]](/spring-boot-modules/spring-boot-artifacts-2) diff --git a/spring-boot-modules/spring-boot-artifacts/pom.xml b/spring-boot-modules/spring-boot-artifacts/pom.xml index 7ed91a6626..0292dc95cf 100644 --- a/spring-boot-modules/spring-boot-artifacts/pom.xml +++ b/spring-boot-modules/spring-boot-artifacts/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-artifacts - war spring-boot-artifacts + war Demo project for Spring Boot com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -102,7 +101,7 @@ maven-failsafe-plugin 2.18 - integration-tests @@ -111,7 +110,7 @@ verify - **/ExternalPropertyFileLoaderIntegrationTest.java @@ -187,14 +186,13 @@ - com.baeldung.boot.Application + com.baeldung.wrapper.DemoApplication 3.1.1 3.3.7-1 2.2 2.2.4 - 18.0 3.1.7 4.5.8 - \ No newline at end of file + diff --git a/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoApplication.java b/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoApplication.java new file mode 100644 index 0000000000..d0a7e96bec --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.wrapper; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = { "com.baeldung" }) +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoController.java b/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoController.java new file mode 100644 index 0000000000..530a1d584e --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts/src/main/java/com/baeldung/wrapper/DemoController.java @@ -0,0 +1,15 @@ +package com.baeldung.wrapper; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class DemoController { + + @GetMapping(value = "/demo") + public String demo(Model model) { + return "index"; + } + +} diff --git a/spring-boot-modules/spring-boot-autoconfiguration/pom.xml b/spring-boot-modules/spring-boot-autoconfiguration/pom.xml index bf8bcc5a87..ef5d4f66dd 100644 --- a/spring-boot-modules/spring-boot-autoconfiguration/pom.xml +++ b/spring-boot-modules/spring-boot-autoconfiguration/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-autoconfiguration 0.0.1-SNAPSHOT - war spring-boot-autoconfiguration + war This is simple boot application demonstrating a custom auto-configuration com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-basic-customization-2/README.md b/spring-boot-modules/spring-boot-basic-customization-2/README.md index f041c1d38a..9488618ca5 100644 --- a/spring-boot-modules/spring-boot-basic-customization-2/README.md +++ b/spring-boot-modules/spring-boot-basic-customization-2/README.md @@ -5,4 +5,6 @@ This module contains articles about Spring Boot customization 2 ### Relevant Articles: - [DispatcherServlet and web.xml in Spring Boot](https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml) - - [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans) \ No newline at end of file + - [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans) + - [What Is OncePerRequestFilter?](https://www.baeldung.com/spring-onceperrequestfilter) + - [Spring Boot Exit Codes](https://www.baeldung.com/spring-boot-exit-codes) diff --git a/spring-boot-modules/spring-boot-basic-customization-2/pom.xml b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml index 6f3cb48b81..b615947de7 100644 --- a/spring-boot-modules/spring-boot-basic-customization-2/pom.xml +++ b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-basic-customization-2 - jar spring-boot-basic-customization-2 + jar Module For Spring Boot Basic Customization 2 com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/event/ExitCodeEventDemoApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/event/ExitCodeEventDemoApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/event/ExitCodeEventDemoApplication.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/event/ExitCodeEventDemoApplication.java diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exception/ExitCodeExceptionMapperDemoApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exception/ExitCodeExceptionMapperDemoApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exception/ExitCodeExceptionMapperDemoApplication.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exception/ExitCodeExceptionMapperDemoApplication.java diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exceptionexitgen/ExceptionExitCodeGeneratorApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exceptionexitgen/ExceptionExitCodeGeneratorApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exceptionexitgen/ExceptionExitCodeGeneratorApplication.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exceptionexitgen/ExceptionExitCodeGeneratorApplication.java diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exceptionexitgen/FailedToStartException.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exceptionexitgen/FailedToStartException.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/exceptionexitgen/FailedToStartException.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/exceptionexitgen/FailedToStartException.java diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/generator/ExitCodeGeneratorDemoApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/generator/ExitCodeGeneratorDemoApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/exitcode/generator/ExitCodeGeneratorDemoApplication.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/exitcode/generator/ExitCodeGeneratorDemoApplication.java diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/AuthenticationFilter.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/AuthenticationFilter.java new file mode 100644 index 0000000000..7ddcde7dc8 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/AuthenticationFilter.java @@ -0,0 +1,34 @@ +package com.baeldung.onceperrequestfilter; + +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class AuthenticationFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws + ServletException, IOException { + String usrName = request.getHeader("userName"); + logger.info("Successfully authenticated user " + + usrName); + filterChain.doFilter(request, response); + } + @Override + protected boolean shouldNotFilterAsyncDispatch() { + return false; + } + @Override + protected boolean shouldNotFilterErrorDispatch() { + return false; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/HelloController.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/HelloController.java new file mode 100644 index 0000000000..0a354c91ac --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/HelloController.java @@ -0,0 +1,40 @@ +package com.baeldung.onceperrequestfilter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.context.request.async.DeferredResult; + +import javax.servlet.http.HttpServletResponse; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Controller +public class HelloController implements AutoCloseable { + + private final ExecutorService executorService = Executors.newCachedThreadPool(); + + private Logger logger = LoggerFactory.getLogger(HelloController.class); + + @GetMapping(path = "/greeting") + public DeferredResult hello(HttpServletResponse response) throws Exception { + DeferredResult deferredResult = new DeferredResult<>(); + executorService.submit(() -> perform(deferredResult)); + return deferredResult; + } + + private void perform(DeferredResult dr) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + dr.setResult("OK"); + } + + @Override + public void close() throws Exception { + executorService.shutdownNow(); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/MyOncePerRequestFilter.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/MyOncePerRequestFilter.java new file mode 100644 index 0000000000..3fd304f86b --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/MyOncePerRequestFilter.java @@ -0,0 +1,29 @@ +package com.baeldung.onceperrequestfilter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class MyOncePerRequestFilter extends OncePerRequestFilter { + private Logger logger = LoggerFactory.getLogger(MyOncePerRequestFilter.class); + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + logger.info("Inside Once Per Request Filter originated by request {}", request.getRequestURI()); + filterChain.doFilter(request, response); + } + + @Override + protected boolean shouldNotFilterAsyncDispatch() { + return true; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/OncePerRequestFilterApp.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/OncePerRequestFilterApp.java new file mode 100644 index 0000000000..ed7be518a3 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/onceperrequestfilter/OncePerRequestFilterApp.java @@ -0,0 +1,12 @@ +package com.baeldung.onceperrequestfilter; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +@SpringBootApplication(scanBasePackages = "com.baeldung.onceperrequestfilter") +public class OncePerRequestFilterApp { + public static void main(String[] args) { + SpringApplication.run(OncePerRequestFilterApp.class, args); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/test/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-basic-customization-2/src/test/java/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-basic-customization-2/src/main/test/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/test/java/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-basic-customization/README.md b/spring-boot-modules/spring-boot-basic-customization/README.md index 6c067fc5a1..a3d9f1b1fc 100644 --- a/spring-boot-modules/spring-boot-basic-customization/README.md +++ b/spring-boot-modules/spring-boot-basic-customization/README.md @@ -11,4 +11,3 @@ This module contains articles about Spring Boot customization - [Spring Boot: Configuring a Main Class](https://www.baeldung.com/spring-boot-main-class) - [How to Define a Spring Boot Filter?](https://www.baeldung.com/spring-boot-add-filter) - [Guide to the Favicon in Spring Boot](https://www.baeldung.com/spring-boot-favicon) - - [Spring Boot Exit Codes](https://www.baeldung.com/spring-boot-exit-codes) diff --git a/spring-boot-modules/spring-boot-basic-customization/pom.xml b/spring-boot-modules/spring-boot-basic-customization/pom.xml index 5ab747cff1..28b30e6bd4 100644 --- a/spring-boot-modules/spring-boot-basic-customization/pom.xml +++ b/spring-boot-modules/spring-boot-basic-customization/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-basic-customization - jar spring-boot-basic-customization + jar Module For Spring Boot Basic Customization com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/bootcustomfilters/FilterConfig.java b/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/bootcustomfilters/FilterConfig.java index 42da61fe14..2bc1b8a55c 100644 --- a/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/bootcustomfilters/FilterConfig.java +++ b/spring-boot-modules/spring-boot-basic-customization/src/main/java/com/baeldung/bootcustomfilters/FilterConfig.java @@ -15,6 +15,7 @@ public class FilterConfig { registrationBean.setFilter(new RequestResponseLoggingFilter()); registrationBean.addUrlPatterns("/users/*"); + registrationBean.setOrder(2); return registrationBean; diff --git a/spring-boot-modules/spring-boot-bootstrap/README.md b/spring-boot-modules/spring-boot-bootstrap/README.md index 02ec52f755..5787f3262d 100644 --- a/spring-boot-modules/spring-boot-bootstrap/README.md +++ b/spring-boot-modules/spring-boot-bootstrap/README.md @@ -9,5 +9,4 @@ This module contains articles about bootstrapping Spring Boot applications. - [Deploy a Spring Boot Application to Google App Engine](https://www.baeldung.com/spring-boot-google-app-engine) - [Deploy a Spring Boot Application to OpenShift](https://www.baeldung.com/spring-boot-deploy-openshift) - [Deploy a Spring Boot Application to AWS Beanstalk](https://www.baeldung.com/spring-boot-deploy-aws-beanstalk) -- [Guide to @SpringBootConfiguration in Spring Boot](https://www.baeldung.com/springbootconfiguration-annotation) - [Implement Health Checks in OpenShift](https://www.baeldung.com/ops/openshift-health-checks) diff --git a/spring-boot-modules/spring-boot-bootstrap/pom.xml b/spring-boot-modules/spring-boot-bootstrap/pom.xml index f94ee9ca31..efcfcb71ee 100644 --- a/spring-boot-modules/spring-boot-bootstrap/pom.xml +++ b/spring-boot-modules/spring-boot-bootstrap/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-bootstrap - jar spring-boot-bootstrap + jar Demo project for Spring Boot com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-camel/pom.xml b/spring-boot-modules/spring-boot-camel/pom.xml index 0069dfdbff..5bda1b2351 100644 --- a/spring-boot-modules/spring-boot-camel/pom.xml +++ b/spring-boot-modules/spring-boot-camel/pom.xml @@ -9,30 +9,29 @@ spring-boot-camel - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT - org.apache.camel + org.apache.camel.springboot camel-servlet-starter ${camel.version} - org.apache.camel + org.apache.camel.springboot camel-jackson-starter ${camel.version} - org.apache.camel + org.apache.camel.springboot camel-swagger-java-starter ${camel.version} - org.apache.camel + org.apache.camel.springboot camel-spring-boot-starter ${camel.version} @@ -65,7 +64,8 @@ - 3.0.0-M4 + 11 + 3.15.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-cassandre/pom.xml b/spring-boot-modules/spring-boot-cassandre/pom.xml index 14849e50d7..e2964183d2 100644 --- a/spring-boot-modules/spring-boot-cassandre/pom.xml +++ b/spring-boot-modules/spring-boot-cassandre/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-cassandre - jar spring-boot-cassandre + jar Cassandre trading bot tutorial - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT diff --git a/spring-boot-modules/spring-boot-ci-cd/pom.xml b/spring-boot-modules/spring-boot-ci-cd/pom.xml index fb1810c62e..39b90a0777 100644 --- a/spring-boot-modules/spring-boot-ci-cd/pom.xml +++ b/spring-boot-modules/spring-boot-ci-cd/pom.xml @@ -5,14 +5,13 @@ 4.0.0 spring-boot-ci-cd 0.0.1-SNAPSHOT - jar spring-boot-ci-cd + jar com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-client/pom.xml b/spring-boot-modules/spring-boot-client/pom.xml index 7f54d0e541..bbdc6cca7d 100644 --- a/spring-boot-modules/spring-boot-client/pom.xml +++ b/spring-boot-modules/spring-boot-client/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-client 0.0.1-SNAPSHOT - war spring-boot-client + war This is simple boot client application for Spring boot actuator test com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -108,7 +107,6 @@ - 18.0 2.2.4 diff --git a/spring-boot-modules/spring-boot-client/src/test/java/com/baeldung/websocket/client/MyStompSessionHandlerIntegrationTest.java b/spring-boot-modules/spring-boot-client/src/test/java/com/baeldung/websocket/client/MyStompSessionHandlerIntegrationTest.java index 57eec935f6..956892729e 100644 --- a/spring-boot-modules/spring-boot-client/src/test/java/com/baeldung/websocket/client/MyStompSessionHandlerIntegrationTest.java +++ b/spring-boot-modules/spring-boot-client/src/test/java/com/baeldung/websocket/client/MyStompSessionHandlerIntegrationTest.java @@ -14,6 +14,6 @@ public class MyStompSessionHandlerIntegrationTest { MyStompSessionHandler sessionHandler = new MyStompSessionHandler(); sessionHandler.afterConnected(mockSession, mockHeader); Mockito.verify(mockSession).subscribe("/topic/messages", sessionHandler); - Mockito.verify(mockSession).send(Mockito.anyString(), Mockito.anyObject()); + Mockito.verify(mockSession).send(Mockito.anyString(), Mockito.any()); } } diff --git a/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/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/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-application/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-library/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-library/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-config-jpa-error/data-jpa-library/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-config-jpa-error/pom.xml b/spring-boot-modules/spring-boot-config-jpa-error/pom.xml index b5207f8997..6291589e7a 100644 --- a/spring-boot-modules/spring-boot-config-jpa-error/pom.xml +++ b/spring-boot-modules/spring-boot-config-jpa-error/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-crud/pom.xml b/spring-boot-modules/spring-boot-crud/pom.xml index 79eccf2fba..7acaa49e87 100644 --- a/spring-boot-modules/spring-boot-crud/pom.xml +++ b/spring-boot-modules/spring-boot-crud/pom.xml @@ -10,7 +10,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -34,11 +33,6 @@ org.springframework.boot spring-boot-starter-test - - org.mockito - mockito-core - test - com.h2database h2 diff --git a/spring-boot-modules/spring-boot-ctx-fluent/pom.xml b/spring-boot-modules/spring-boot-ctx-fluent/pom.xml index 8a7aca076e..4b0d99f309 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/pom.xml +++ b/spring-boot-modules/spring-boot-ctx-fluent/pom.xml @@ -5,14 +5,13 @@ 4.0.0 spring-boot-ctx-fluent 0.0.1-SNAPSHOT - jar spring-boot-ctx-fluent + jar com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx1/Ctx1Controller.java b/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx1/Ctx1Controller.java index 9c7667db35..2de42251e4 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx1/Ctx1Controller.java +++ b/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx1/Ctx1Controller.java @@ -1,22 +1,18 @@ package com.baeldung.ctx1; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseBody; - import com.baeldung.parent.IHomeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; -@Controller +@RestController public class Ctx1Controller { @Autowired - IHomeService homeService; + private IHomeService homeService; @GetMapping("/home") - @ResponseBody public String greeting() { - return homeService.getGreeting(); } } diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx2/Ctx2Controller.java b/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx2/Ctx2Controller.java index 850fd8021c..1b7edf6710 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx2/Ctx2Controller.java +++ b/spring-boot-modules/spring-boot-ctx-fluent/src/main/java/com/baeldung/ctx2/Ctx2Controller.java @@ -1,18 +1,17 @@ package com.baeldung.ctx2; +import com.baeldung.parent.IHomeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.parent.IHomeService; - @RestController public class Ctx2Controller { @Autowired - IHomeService homeService; + private IHomeService homeService; - @GetMapping(value = "/greeting", produces = "application/json") + @GetMapping("/greeting") public String getGreeting() { return homeService.getGreeting(); } diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx1.properties b/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx1.properties index 2b618d4177..d0af43abdd 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx1.properties +++ b/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx1.properties @@ -1,4 +1,4 @@ -server.port=8081 +server.port=8074 server.servlet.context-path=/ctx1 #logging.level=debug spring.application.admin.enabled=false diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx2.properties b/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx2.properties index f3599e17e0..7cd48d2f07 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx2.properties +++ b/spring-boot-modules/spring-boot-ctx-fluent/src/main/resources/ctx2.properties @@ -1,4 +1,4 @@ -server.port=8082 +server.port=8075 server.servlet.context-path=/ctx2 spring.application.admin.enabled=false diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java index ca8989724b..07242452bf 100644 --- a/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java @@ -7,7 +7,7 @@ import com.baeldung.parent.App; public class SpringContextTest { @Test - public final void testMain() throws Exception { + public final void testMain() { App.main(new String[] {}); } } diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/pom.xml b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/pom.xml index 815c3e8366..c4759af373 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-sample-app/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-custom-starter 0.0.1-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter/pom.xml b/spring-boot-modules/spring-boot-custom-starter/greeter/pom.xml index f96880b1cf..5c0580d29a 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/greeter/pom.xml @@ -8,10 +8,9 @@ greeter - com.baeldung - parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-custom-starter 0.0.1-SNAPSHOT - ../../../parent-boot-2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/application/pom.xml b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/application/pom.xml index 1c26ec32d3..a00c3a3c57 100644 --- a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/application/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/application/pom.xml @@ -9,9 +9,8 @@ com.baeldung - parent-boot-2 + parent-multi-module 0.0.1-SNAPSHOT - ../../../../parent-boot-2 diff --git a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/library/pom.xml b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/library/pom.xml index 5d45de0d1d..6e7b3ce78a 100644 --- a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/library/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/library/pom.xml @@ -9,9 +9,8 @@ com.baeldung - parent-boot-2 + parent-multi-module 0.0.1-SNAPSHOT - ../../../../parent-boot-2 diff --git a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/pom.xml b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/pom.xml index 2a483a8fef..4bc8434d43 100644 --- a/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/parent-multi-module/pom.xml @@ -8,6 +8,12 @@ 0.0.1-SNAPSHOT pom + + com.baeldung.spring-boot-modules + spring-boot-custom-starter + 0.0.1-SNAPSHOT + + library application diff --git a/spring-boot-modules/spring-boot-custom-starter/pom.xml b/spring-boot-modules/spring-boot-custom-starter/pom.xml index 27e3a03153..aee98b125e 100644 --- a/spring-boot-modules/spring-boot-custom-starter/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-data-2/README.md b/spring-boot-modules/spring-boot-data-2/README.md index 875ee502b4..b99356492b 100644 --- a/spring-boot-modules/spring-boot-data-2/README.md +++ b/spring-boot-modules/spring-boot-data-2/README.md @@ -1,5 +1,6 @@ ### Relevant Articles: +- [HttpMessageNotWritableException: No Converter for [class …] With Preset Content-Type](https://www.baeldung.com/spring-no-converter-with-preset) - [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper) - [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found) - [Creating a Read-Only Repository with Spring Data](https://www.baeldung.com/spring-data-read-only-repository) diff --git a/spring-boot-modules/spring-boot-data-2/pom.xml b/spring-boot-modules/spring-boot-data-2/pom.xml index b7006782c8..a3c2430497 100644 --- a/spring-boot-modules/spring-boot-data-2/pom.xml +++ b/spring-boot-modules/spring-boot-data-2/pom.xml @@ -9,7 +9,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java index 21cb98710d..4119b624e1 100644 --- a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java @@ -1,5 +1,6 @@ package com.baeldung.boot.noconverterfound.controller; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -18,4 +19,14 @@ public class StudentRestController { return ResponseEntity.ok(new Student(id, "John", "Wiliams", "AA")); } + @GetMapping(value = "/student/v2/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getV2(@PathVariable("id") int id) { + return ResponseEntity.ok(new Student(id, "Kevin", "Cruyff", "AA")); + } + + @GetMapping(value = "/student/v3/{id}", produces = MediaType.APPLICATION_XML_VALUE) + public ResponseEntity getV3(@PathVariable("id") int id) { + return ResponseEntity.ok(new Student(id, "Robert", "Miller", "BB")); + } + } diff --git a/spring-boot-modules/spring-boot-data-2/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-data-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-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/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java index f8ded91e65..6f89ef0e58 100644 --- a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,16 +26,16 @@ public class NoConverterFoundIntegrationTest { /* Remove Getters from Student class to successfully run this test case * @Test public void whenGettersNotDefined_thenThrowException() throws Exception { - + String url = "/api/student/1"; - + this.mockMvc.perform(get(url)) .andExpect(status().isInternalServerError()) .andExpect(result -> assertThat(result.getResolvedException()) .isInstanceOf(HttpMessageNotWritableException.class)) .andExpect(result -> assertThat(result.getResolvedException().getMessage()) .contains("No converter found for return value of type")); - + } */ @@ -44,9 +45,28 @@ public class NoConverterFoundIntegrationTest { String url = "/api/student/2"; this.mockMvc.perform(get(url)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.firstName").value("John")); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.firstName").value("John")); + } + @Test + public void whenJsonConverterIsFound_thenReturnResponse() throws Exception { + String url = "/api/student/v2/1"; + + this.mockMvc.perform(get(url)) + .andExpect(status().isOk()) + .andExpect(content().json("{'id':1,'firstName':'Kevin','lastName':'Cruyff', 'grade':'AA'}")); + } + + @Test + public void whenConverterNotFound_thenThrowException() throws Exception { + String url = "/api/student/v3/1"; + + this.mockMvc.perform(get(url)) + .andExpect(status().isInternalServerError()) + .andExpect(result -> assertThat(result.getResolvedException()).isInstanceOf(HttpMessageNotWritableException.class)) + .andExpect(result -> assertThat(result.getResolvedException() + .getMessage()).contains("No converter for [class com.baeldung.boot.noconverterfound.model.Student] with preset Content-Type")); } } diff --git a/spring-boot-modules/spring-boot-data-2/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-data-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data/pom.xml b/spring-boot-modules/spring-boot-data/pom.xml index 447b730c02..18360bbd8b 100644 --- a/spring-boot-modules/spring-boot-data/pom.xml +++ b/spring-boot-modules/spring-boot-data/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-data - war spring-boot-data + war Spring Boot Data Module com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -36,7 +35,6 @@ com.h2database h2 - ${h2.version} org.springframework.boot diff --git a/spring-boot-modules/spring-boot-deployment/pom.xml b/spring-boot-modules/spring-boot-deployment/pom.xml index 7c78d20afc..7a9c2096f1 100644 --- a/spring-boot-modules/spring-boot-deployment/pom.xml +++ b/spring-boot-modules/spring-boot-deployment/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -175,7 +174,6 @@ 3.1.1 3.3.7-1 2.2 - 18.0 3.1.7 4.5.8 diff --git a/spring-boot-modules/spring-boot-di/pom.xml b/spring-boot-modules/spring-boot-di/pom.xml index 0e9fb49a95..d3bfdc4afc 100644 --- a/spring-boot-modules/spring-boot-di/pom.xml +++ b/spring-boot-modules/spring-boot-di/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-di - jar spring-boot-di + jar Module For Spring Boot DI com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml index deee4e435f..ace21410ea 100644 --- a/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-disable-logging 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml index 0524f9d401..b71e1066e7 100644 --- a/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-disable-logging 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml index 0990209ff9..37fad3ec53 100644 --- a/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml @@ -10,7 +10,6 @@ com.baeldung.spring-boot-modules spring-boot-disable-logging 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-disable-logging/pom.xml b/spring-boot-modules/spring-boot-disable-logging/pom.xml index 65de521c63..b7bbbe0f8d 100644 --- a/spring-boot-modules/spring-boot-disable-logging/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/pom.xml @@ -5,14 +5,13 @@ 4.0.0 spring-boot-disable-logging 1.0.0-SNAPSHOT - pom spring-boot-disable-logging + pom com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-environment/pom.xml b/spring-boot-modules/spring-boot-environment/pom.xml index d4b260ee3d..3ea591f561 100644 --- a/spring-boot-modules/spring-boot-environment/pom.xml +++ b/spring-boot-modules/spring-boot-environment/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -30,17 +29,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - - org.springframework.boot spring-boot-starter-data-jpa @@ -149,10 +137,9 @@ 2.2 - 18.0 3.1.7 4.5.8 - 2020.0.0 + 2021.0.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/prefix/PrefixController.java b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/prefix/PrefixController.java index 00b728c7ae..dc6b0cd513 100644 --- a/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/prefix/PrefixController.java +++ b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/prefix/PrefixController.java @@ -1,6 +1,7 @@ package com.baeldung.prefix; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -8,12 +9,12 @@ import org.springframework.web.bind.annotation.GetMapping; @Controller public class PrefixController { - @Value(value = "${server.port}") - private int serverPort; + @Autowired + private Environment environment; @GetMapping("/prefix") public String getServerPortInfo(final Model model) { - model.addAttribute("serverPort", serverPort); + model.addAttribute("serverPort", environment.getProperty("server.port")); return "prefix"; } } diff --git a/spring-boot-modules/spring-boot-exceptions/pom.xml b/spring-boot-modules/spring-boot-exceptions/pom.xml index cec1bab4ff..b1240957f6 100644 --- a/spring-boot-modules/spring-boot-exceptions/pom.xml +++ b/spring-boot-modules/spring-boot-exceptions/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-flowable/pom.xml b/spring-boot-modules/spring-boot-flowable/pom.xml index 320a684880..50500c3de6 100644 --- a/spring-boot-modules/spring-boot-flowable/pom.xml +++ b/spring-boot-modules/spring-boot-flowable/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -40,11 +39,6 @@ spring-boot-starter-test test - - org.junit.jupiter - junit-jupiter-engine - test - diff --git a/spring-boot-modules/spring-boot-groovy/pom.xml b/spring-boot-modules/spring-boot-groovy/pom.xml index ea9f3231cd..820bb0fd7a 100644 --- a/spring-boot-modules/spring-boot-groovy/pom.xml +++ b/spring-boot-modules/spring-boot-groovy/pom.xml @@ -10,10 +10,9 @@ Spring Boot Todo Application with Groovy - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT diff --git a/spring-boot-modules/spring-boot-jasypt/pom.xml b/spring-boot-modules/spring-boot-jasypt/pom.xml index 0a37c545ac..8595b9c639 100644 --- a/spring-boot-modules/spring-boot-jasypt/pom.xml +++ b/spring-boot-modules/spring-boot-jasypt/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-keycloak/.gitignore b/spring-boot-modules/spring-boot-keycloak/.gitignore deleted file mode 100644 index 2af7cefb0a..0000000000 --- a/spring-boot-modules/spring-boot-keycloak/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties b/spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 9dda3b659b..0000000000 --- a/spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip diff --git a/spring-boot-modules/spring-boot-keycloak/README.md b/spring-boot-modules/spring-boot-keycloak/README.md index 2aff4664a6..7a1323d10e 100644 --- a/spring-boot-modules/spring-boot-keycloak/README.md +++ b/spring-boot-modules/spring-boot-keycloak/README.md @@ -8,4 +8,4 @@ This module contains articles about Keycloak in Spring Boot projects. - [Customizing the Login Page for Keycloak](https://www.baeldung.com/keycloak-custom-login-page) - [Keycloak User Self-Registration](https://www.baeldung.com/keycloak-user-registration) - [Customizing Themes for Keycloak](https://www.baeldung.com/spring-keycloak-custom-themes) - +- [Securing SOAP Web Services With Keycloak](https://www.baeldung.com/soap-keycloak) diff --git a/spring-boot-modules/spring-boot-keycloak/pom.xml b/spring-boot-modules/spring-boot-keycloak/pom.xml index b80dbfa191..09ddcaa724 100644 --- a/spring-boot-modules/spring-boot-keycloak/pom.xml +++ b/spring-boot-modules/spring-boot-keycloak/pom.xml @@ -64,6 +64,20 @@ org.springframework.boot spring-boot-starter-thymeleaf + + wsdl4j + wsdl4j + 1.6.3 + + + org.springframework.boot + spring-boot-starter-web-services + + + org.springframework.security + spring-security-test + test + @@ -72,11 +86,31 @@ org.springframework.boot spring-boot-maven-plugin + + org.codehaus.mojo + jaxb2-maven-plugin + 2.5.0 + + + xjc + + xjc + + + + + com.baeldung + + src/main/resources/products.xsd + + + + - 13.0.1 + 15.0.2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java index 895ac8c562..78023aff8f 100644 --- a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java @@ -1,24 +1,19 @@ package com.baeldung.keycloak; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; -import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents; +import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; -@Configuration -@EnableWebSecurity -@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) +@KeycloakConfiguration class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { // Submits the KeycloakAuthenticationProvider to the AuthenticationManager @Autowired diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSecurityConfig.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSecurityConfig.java new file mode 100644 index 0000000000..66a17f4967 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSecurityConfig.java @@ -0,0 +1,54 @@ +package com.baeldung.keycloaksoap; + +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; +import org.keycloak.adapters.springsecurity.KeycloakConfiguration; +import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; +import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; + +@KeycloakConfiguration +@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "true") +@EnableGlobalMethodSecurity(jsr250Enabled = true) +public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + //@formatter:off + http + .csrf() + .disable() + .authorizeRequests() + .anyRequest() + .permitAll(); + //@formatter:on + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) { + KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); + keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); + auth.authenticationProvider(keycloakAuthenticationProvider); + } + + @Bean + @Override + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); + } + + @Bean + public KeycloakConfigResolver keycloakSpringBootConfigResolver() { + return new KeycloakSpringBootConfigResolver(); + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSoapServicesApplication.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSoapServicesApplication.java new file mode 100644 index 0000000000..4cf60a804a --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/KeycloakSoapServicesApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.keycloaksoap; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class KeycloakSoapServicesApplication { + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(KeycloakSoapServicesApplication.class); + application.setAdditionalProfiles("keycloak"); + application.run(args); + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/ProductsEndpoint.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/ProductsEndpoint.java new file mode 100644 index 0000000000..58f7739af0 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/ProductsEndpoint.java @@ -0,0 +1,42 @@ +package com.baeldung.keycloaksoap; + +import com.baeldung.DeleteProductRequest; +import com.baeldung.DeleteProductResponse; +import com.baeldung.GetProductDetailsRequest; +import com.baeldung.GetProductDetailsResponse; +import com.baeldung.Product; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; + +import javax.annotation.security.RolesAllowed; +import java.util.Map; + +@Endpoint +public class ProductsEndpoint { + + private final Map productMap; + + public ProductsEndpoint(Map productMap) { + this.productMap = productMap; + } + + @RolesAllowed("user") + @PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "getProductDetailsRequest") + @ResponsePayload + public GetProductDetailsResponse getProductDetails(@RequestPayload GetProductDetailsRequest request) { + GetProductDetailsResponse response = new GetProductDetailsResponse(); + response.setProduct(productMap.get(request.getId())); + return response; + } + + @RolesAllowed("admin") + @PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "deleteProductRequest") + @ResponsePayload + public DeleteProductResponse deleteProduct(@RequestPayload DeleteProductRequest request) { + DeleteProductResponse response = new DeleteProductResponse(); + response.setMessage("Success! Deleted the product with the id - "+request.getId()); + return response; + } +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/WebServiceConfig.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/WebServiceConfig.java new file mode 100644 index 0000000000..00d128fa12 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloaksoap/WebServiceConfig.java @@ -0,0 +1,75 @@ +package com.baeldung.keycloaksoap; + +import com.baeldung.Product; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.ws.config.annotation.EnableWs; +import org.springframework.ws.config.annotation.WsConfigurerAdapter; +import org.springframework.ws.transport.http.MessageDispatcherServlet; +import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; +import org.springframework.xml.xsd.SimpleXsdSchema; +import org.springframework.xml.xsd.XsdSchema; + +import java.util.HashMap; +import java.util.Map; + +@EnableWs +@Configuration +public class WebServiceConfig extends WsConfigurerAdapter { + + @Value("${ws.api.path:/ws/api/v1/*}") + private String webserviceApiPath; + @Value("${ws.port.type.name:ProductsPort}") + private String webservicePortTypeName; + @Value("${ws.target.namespace:http://www.baeldung.com/springbootsoap/keycloak}") + private String webserviceTargetNamespace; + @Value("${ws.location.uri:http://localhost:18080/ws/api/v1/}") + private String locationUri; + + @Bean + public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { + MessageDispatcherServlet servlet = new MessageDispatcherServlet(); + servlet.setApplicationContext(applicationContext); + servlet.setTransformWsdlLocations(true); + return new ServletRegistrationBean<>(servlet, webserviceApiPath); + } + + @Bean(name = "products") + public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema productsSchema) { + DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); + wsdl11Definition.setPortTypeName(webservicePortTypeName); + wsdl11Definition.setTargetNamespace(webserviceTargetNamespace); + wsdl11Definition.setLocationUri(locationUri); + wsdl11Definition.setSchema(productsSchema); + return wsdl11Definition; + } + + @Bean + public XsdSchema productsSchema() { + return new SimpleXsdSchema(new ClassPathResource("products.xsd")); + } + + @Bean + public Map getProducts() + { + Map map = new HashMap<>(); + Product foldsack= new Product(); + foldsack.setId("1"); + foldsack.setName("Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops"); + foldsack.setDescription("Your perfect pack for everyday use and walks in the forest. "); + + Product shirt= new Product(); + shirt.setId("2"); + shirt.setName("Mens Casual Premium Slim Fit T-Shirts"); + shirt.setDescription("Slim-fitting style, contrast raglan long sleeve, three-button henley placket."); + + map.put("1", foldsack); + map.put("2", shirt); + return map; + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/resources/application-keycloak.properties b/spring-boot-modules/spring-boot-keycloak/src/main/resources/application-keycloak.properties new file mode 100644 index 0000000000..0a28b7ac48 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/resources/application-keycloak.properties @@ -0,0 +1,17 @@ +server.port=18080 + +keycloak.enabled=true +keycloak.realm=baeldung-soap-services +keycloak.auth-server-url=http://localhost:8080/auth +keycloak.bearer-only=true +keycloak.credentials.secret=14da6f9e-261f-489a-9bf0-1441e4a9ddc4 +keycloak.ssl-required=external +keycloak.resource=baeldung-soap-services +keycloak.use-resource-role-mappings=true + + +# Custom properties begin here +ws.api.path=/ws/api/v1/* +ws.port.type.name=ProductsPort +ws.target.namespace=http://www.baeldung.com/springbootsoap/keycloak +ws.location.uri=http://localhost:18080/ws/api/v1/ \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/resources/products.xsd b/spring-boot-modules/spring-boot-keycloak/src/main/resources/products.xsd new file mode 100644 index 0000000000..b147118e96 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/main/resources/products.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/KeycloakSoapIntegrationTest.java b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/KeycloakSoapIntegrationTest.java new file mode 100644 index 0000000000..e0de897044 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/KeycloakSoapIntegrationTest.java @@ -0,0 +1,153 @@ +package com.baeldung.keycloaksoap; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import java.util.Objects; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * The class contains Live/Integration tests. + * These tests expect that the Keycloak server is up and running on port 8080. + * The tests may fail without a Keycloak server. + */ +@DisplayName("Keycloak SOAP Webservice Unit Tests") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles("test") +@AutoConfigureMockMvc +class KeycloakSoapIntegrationTest { + + private static final Logger logger = LoggerFactory.getLogger(KeycloakSoapIntegrationTest.class); + @LocalServerPort + private int port; + @Autowired + private TestRestTemplate restTemplate; + @Autowired + private ObjectMapper objectMapper; + @Value("${grant.type}") + private String grantType; + @Value("${client.id}") + private String clientId; + @Value("${client.secret}") + private String clientSecret; + @Value("${url}") + private String keycloakUrl; + + /** + * Test a happy flow. Test the janedoe user. + * This user should be configured in Keycloak server with a role user + */ + @Test + @DisplayName("Get Products With Access Token") + void givenAccessToken_whenGetProducts_thenReturnProduct() { + + HttpHeaders headers = new HttpHeaders(); + headers.set("content-type", "text/xml"); + headers.set("Authorization", "Bearer " + generateToken("janedoe", "password")); + HttpEntity request = new HttpEntity<>(Utility.getGetProductDetailsRequest(), headers); + ResponseEntity responseEntity = restTemplate.postForEntity("http://localhost:" + port + "/ws/api/v1/", request, String.class); + + assertThat(responseEntity).isNotNull(); + assertThat(responseEntity.getStatusCodeValue()).isEqualTo(HttpStatus.OK.value()); + assertThat(responseEntity.getBody()).isNotBlank(); + assertThat(responseEntity.getBody()).containsIgnoringCase(":id>1janeadoe user. + * Keycloak returns Unauthorized. Assert 401 status and empty body. + */ + @Test + @DisplayName("Get Products With Wrong Access Token") + void givenWrongAccessToken_whenGetProducts_thenReturnError() { + + HttpHeaders headers = new HttpHeaders(); + headers.set("content-type", "text/xml"); + headers.set("Authorization", "Bearer " + generateToken("janeadoe", "password")); + HttpEntity request = new HttpEntity<>(Utility.getGetProductDetailsRequest(), headers); + ResponseEntity responseEntity = restTemplate.postForEntity("http://localhost:" + port + "/ws/api/v1/", request, String.class); + assertThat(responseEntity).isNotNull(); + assertThat(responseEntity.getStatusCodeValue()).isEqualTo(HttpStatus.UNAUTHORIZED.value()); + assertThat(responseEntity.getBody()).isBlank(); + } + + /** + * Happy flow to test deleteProduct operation. Test the jhondoe user. + * This user should be configured in Keycloak server with a role user + */ + @Test + @DisplayName("Delete Product With Access Token") + void givenAccessToken_whenDeleteProduct_thenReturnSuccess() { + HttpHeaders headers = new HttpHeaders(); + headers.set("content-type", "text/xml"); + headers.set("Authorization", "Bearer " + generateToken("jhondoe", "password")); + HttpEntity request = new HttpEntity<>(Utility.getDeleteProductsRequest(), headers); + ResponseEntity responseEntity = restTemplate.postForEntity("http://localhost:" + port + "/ws/api/v1/", request, String.class); + + assertThat(responseEntity).isNotNull(); + assertThat(responseEntity.getStatusCodeValue()).isEqualTo(HttpStatus.OK.value()); + assertThat(responseEntity.getBody()).isNotBlank(); + assertThat(responseEntity.getBody()).containsIgnoringCase("Deleted the product with the id"); + } + + /** + * Negative flow to test . Test the janedoe user. + * Obtain the access token of janedoe and access the admin operation deleteProduct + * Assume janedoe has restricted access to deleteProduct operation + */ + @Test + @DisplayName("Delete Products With Unauthorized Access Token") + void givenUnauthorizedAccessToken_whenDeleteProduct_thenReturnUnauthorized() { + HttpHeaders headers = new HttpHeaders(); + headers.set("content-type", "text/xml"); + headers.set("Authorization", "Bearer " + generateToken("janedoe", "password")); + HttpEntity request = new HttpEntity<>(Utility.getDeleteProductsRequest(), headers); + ResponseEntity responseEntity = restTemplate.postForEntity("http://localhost:" + port + "/ws/api/v1/", request, String.class); + + assertThat(responseEntity).isNotNull(); + assertThat(responseEntity.getStatusCodeValue()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value()); + assertThat(responseEntity.getBody()).isNotBlank(); + assertThat(responseEntity.getBody()).containsIgnoringCase("Access is denied"); + } + + private String generateToken(String username, String password) { + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("grant_type", grantType); + map.add("client_id", clientId); + map.add("client_secret", clientSecret); + map.add("username", username); + map.add("password", password); + HttpEntity> entity = new HttpEntity<>(map, headers); + ResponseEntity response = restTemplate.exchange(keycloakUrl, HttpMethod.POST, entity, String.class); + return Objects.requireNonNull(response.getBody()).contains("access_token") ? objectMapper.readTree(response.getBody()).get("access_token").asText() : ""; + } catch (Exception ex) { + logger.error("There is an internal server error. Returning an empty access token", ex); + return ""; + } + + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/Utility.java b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/Utility.java new file mode 100644 index 0000000000..1535d9f171 --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloaksoap/Utility.java @@ -0,0 +1,12 @@ +package com.baeldung.keycloaksoap; + +public class Utility { + public static String getGetProductDetailsRequest() { + return "\n" + " \n" + " \n" + " \n" + + " 1\n" + " \n" + " \n" + ""; + } + public static String getDeleteProductsRequest() { + return "\n" + " \n" + " \n" + " \n" + + " 1\n" + " \n" + " \n" + ""; + } +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/test/resources/application-test.properties b/spring-boot-modules/spring-boot-keycloak/src/test/resources/application-test.properties new file mode 100644 index 0000000000..a818b5be7a --- /dev/null +++ b/spring-boot-modules/spring-boot-keycloak/src/test/resources/application-test.properties @@ -0,0 +1,4 @@ +grant.type=password +client.id=baeldung-soap-services +client.secret=d2ba7af8-f7d2-4c97-b4a5-3c88b59920ae +url=http://localhost:8080/auth/realms/baeldung-soap-services/protocol/openid-connect/token diff --git a/spring-boot-modules/spring-boot-libraries-2/README.md b/spring-boot-modules/spring-boot-libraries-2/README.md index 7bf51b5424..cf07279258 100644 --- a/spring-boot-modules/spring-boot-libraries-2/README.md +++ b/spring-boot-modules/spring-boot-libraries-2/README.md @@ -6,3 +6,5 @@ This module contains articles about various Spring Boot libraries - [Background Jobs in Spring with JobRunr](https://www.baeldung.com/java-jobrunr-spring) - [Open API Server Implementation Using OpenAPI Generator](https://www.baeldung.com/java-openapi-generator-server) +- [An Introduction to Kong](https://www.baeldung.com/kong) + More articles: [[prev -->]](/spring-boot-modules/spring-boot-libraries) diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/JobRunrSpringBootApp.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/JobRunrSpringBootApp.java index 061dba15bf..3821332132 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/JobRunrSpringBootApp.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/JobRunrSpringBootApp.java @@ -1,15 +1,11 @@ package com.baeldung; import com.baeldung.jobrunr.service.SampleJobService; -import org.jobrunr.jobs.mappers.JobMapper; import org.jobrunr.scheduling.JobScheduler; import org.jobrunr.scheduling.cron.Cron; -import org.jobrunr.storage.InMemoryStorageProvider; -import org.jobrunr.storage.StorageProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; import javax.annotation.PostConstruct; @@ -23,13 +19,6 @@ public class JobRunrSpringBootApp { SpringApplication.run(JobRunrSpringBootApp.class, args); } - @Bean - public StorageProvider storageProvider(JobMapper jobMapper) { - InMemoryStorageProvider storageProvider = new InMemoryStorageProvider(); - storageProvider.setJobMapper(jobMapper); - return storageProvider; - } - @PostConstruct public void scheduleRecurrently() { jobScheduler.scheduleRecurrently(Cron.every5minutes(), x -> x.executeSampleJob("a recurring job")); diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/config/StorageProviderConfig.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/config/StorageProviderConfig.java new file mode 100644 index 0000000000..e4b8cf12d7 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/config/StorageProviderConfig.java @@ -0,0 +1,18 @@ +package com.baeldung.config; + +import org.jobrunr.jobs.mappers.JobMapper; +import org.jobrunr.storage.InMemoryStorageProvider; +import org.jobrunr.storage.StorageProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class StorageProviderConfig { + + @Bean + public StorageProvider storageProvider(JobMapper jobMapper) { + InMemoryStorageProvider storageProvider = new InMemoryStorageProvider(); + storageProvider.setJobMapper(jobMapper); + return storageProvider; + } +} diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/QueryController.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/kong/QueryController.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/QueryController.java rename to spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/kong/QueryController.java diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/StockApp.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/kong/StockApp.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/StockApp.java rename to spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/kong/StockApp.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/APIObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/APIObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/APIObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/APIObject.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/ConsumerObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/ConsumerObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/ConsumerObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/ConsumerObject.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/PluginObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/PluginObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/PluginObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/PluginObject.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/TargetObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/TargetObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/TargetObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/TargetObject.java diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/UpstreamObject.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/UpstreamObject.java similarity index 100% rename from spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/UpstreamObject.java rename to spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/kong/domain/UpstreamObject.java diff --git a/spring-boot-modules/spring-boot-libraries-comparison/README.md b/spring-boot-modules/spring-boot-libraries-comparison/README.md new file mode 100644 index 0000000000..3efdac2a4c --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/README.md @@ -0,0 +1,7 @@ +## Spring Boot Libraries + +This module contains articles about various Spring Boot libraries Comparison + +### Relevant Articles: + +- [GraphQL vs REST](https://www.baeldung.com/graphql-vs-rest/) \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-comparison/pom.xml b/spring-boot-modules/spring-boot-libraries-comparison/pom.xml new file mode 100644 index 0000000000..59d0e75be3 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + spring-boot-libraries-comparison + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.data + spring-data-jpa + + + com.graphql-java + graphql-spring-boot-starter + ${graphql-spring-boot-starter.version} + + + com.graphql-java + graphql-java-tools + ${graphql-java-tools.version} + + + com.graphql-java + graphiql-spring-boot-starter + ${graphql-spring-boot-starter.version} + + + + + + 5.0.2 + 5.2.4 + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/GraphqlVsRestApplication.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/GraphqlVsRestApplication.java new file mode 100644 index 0000000000..29a3ef1e0f --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/GraphqlVsRestApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.graphqlvsrest; + +import com.baeldung.graphqlvsrest.configuration.GraphqlConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.context.annotation.Import; + +@SpringBootApplication +@Import(GraphqlConfiguration.class) +@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class}) +public class GraphqlVsRestApplication { + + public static void main(String[] args) { + SpringApplication.run(GraphqlVsRestApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/configuration/GraphqlConfiguration.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/configuration/GraphqlConfiguration.java new file mode 100644 index 0000000000..c100a03143 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/configuration/GraphqlConfiguration.java @@ -0,0 +1,35 @@ +package com.baeldung.graphqlvsrest.configuration; + +import com.baeldung.graphqlvsrest.repository.OrderRepository; +import com.baeldung.graphqlvsrest.resolver.Mutation; +import com.baeldung.graphqlvsrest.resolver.ProductResolver; +import com.baeldung.graphqlvsrest.resolver.Query; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class GraphqlConfiguration { + + @Autowired + ProductRepository productRepository; + + @Autowired + OrderRepository orderRepository; + + @Bean + public Query query() { + return new Query(productRepository); + } + + @Bean + public ProductResolver productResolver(){ + return new ProductResolver(orderRepository); + } + + @Bean + public Mutation mutation() { + return new Mutation(productRepository); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/OrderController.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/OrderController.java new file mode 100644 index 0000000000..14f0468bbd --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/OrderController.java @@ -0,0 +1,25 @@ +package com.baeldung.graphqlvsrest.controller; + +import com.baeldung.graphqlvsrest.entity.Order; +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; +import com.baeldung.graphqlvsrest.repository.OrderRepository; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("order") +public class OrderController { + + @Autowired + OrderRepository orderRepository; + + @GetMapping() + public List getOrders(@RequestParam("product-id") Integer productId){ + return orderRepository.getOrdersByProduct(productId); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/ProductController.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/ProductController.java new file mode 100644 index 0000000000..2fdee8765a --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/controller/ProductController.java @@ -0,0 +1,38 @@ +package com.baeldung.graphqlvsrest.controller; + +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("product") +public class ProductController { + + @Autowired + ProductRepository productRepository; + + @GetMapping + public List getProducts(Pageable pageable){ + return productRepository.getProducts(pageable.getPageSize(), pageable.getPageNumber()); + } + + @GetMapping("/{product-id}") + public Product getProducts(@PathVariable("product-id") Integer productId){ + return productRepository.getProduct(productId); + } + + @PostMapping + public Product save(@RequestBody ProductModel productModel){ + return productRepository.save(productModel); + } + + @PutMapping("/{product-id}") + public Product update(@PathVariable("product-id") Integer productId, @RequestBody ProductModel productModel){ + return productRepository.update(productId, productModel); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Order.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Order.java new file mode 100644 index 0000000000..89606e9897 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Order.java @@ -0,0 +1,58 @@ +package com.baeldung.graphqlvsrest.entity; + +public class Order { + private Integer id; + private Integer product_id; + private String customer_uuid; + private String status; + private String address; + private String creation_date; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getProduct_id() { + return product_id; + } + + public void setProduct_id(Integer product_id) { + this.product_id = product_id; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCustomer_uuid() { + return customer_uuid; + } + + public void setCustomer_uuid(String customer_uuid) { + this.customer_uuid = customer_uuid; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getCreation_date() { + return creation_date; + } + + public void setCreation_date(String creation_date) { + this.creation_date = creation_date; + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Product.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Product.java new file mode 100644 index 0000000000..2da9244c92 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/entity/Product.java @@ -0,0 +1,115 @@ +package com.baeldung.graphqlvsrest.entity; + +import com.baeldung.graphqlvsrest.model.ProductModel; + +import java.util.List; + +public class Product { + private Integer id; + private String name; + private String description; + private String status; + private String currency; + private Double price; + private List image_url; + private List video_url; + private Integer stock; + private Float average_rating; + + public Product(Integer id, ProductModel productModel) { + this.id = id; + this.name = productModel.getName(); + this.description = productModel.getDescription(); + this.currency = productModel.getCurrency(); + this.price = productModel.getPrice(); + this.stock = productModel.getStock(); + this.image_url = productModel.getImage_url(); + this.video_url = productModel.getVideo_url(); + this.average_rating = 0F; + this.status = productModel.getStatus(); + } + + public Product(){ + + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public List getImage_url() { + return image_url; + } + + public void setImage_url(List image_url) { + this.image_url = image_url; + } + + public List getVideo_url() { + return video_url; + } + + public void setVideo_url(List video_url) { + this.video_url = video_url; + } + + public Integer getStock() { + return stock; + } + + public void setStock(Integer stock) { + this.stock = stock; + } + + public Float getAverage_rating() { + return average_rating; + } + + public void setAverage_rating(Float average_rating) { + this.average_rating = average_rating; + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/model/ProductModel.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/model/ProductModel.java new file mode 100644 index 0000000000..db7a3ba54e --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/model/ProductModel.java @@ -0,0 +1,92 @@ +package com.baeldung.graphqlvsrest.model; + +import java.util.List; + +public class ProductModel { + private String name; + private String description; + private String status; + private String currency; + private Double price; + private List image_url; + private List video_url; + private Integer stock; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public List getImage_url() { + return image_url; + } + + public void setImage_url(List image_url) { + this.image_url = image_url; + } + + public List getVideo_url() { + return video_url; + } + + public void setVideo_url(List video_url) { + this.video_url = video_url; + } + + public Integer getStock() { + return stock; + } + + public void setStock(Integer stock) { + this.stock = stock; + } + + @Override + public String toString() { + return "ProductModel{" + + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", status='" + status + '\'' + + ", currency='" + currency + '\'' + + ", price=" + price + + ", image_url=" + image_url + + ", video_url=" + video_url + + ", stock=" + stock + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/OrderRepository.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/OrderRepository.java new file mode 100644 index 0000000000..92cc288426 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/OrderRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.graphqlvsrest.repository; + +import com.baeldung.graphqlvsrest.entity.Order; +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; + +import java.util.List; + +public interface OrderRepository { + List getOrdersByProduct(Integer productId); +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/ProductRepository.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/ProductRepository.java new file mode 100644 index 0000000000..c0fb12327f --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/ProductRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.graphqlvsrest.repository; + +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; + +import java.util.List; + +public interface ProductRepository { + List getProducts(Integer pageSize, Integer pageNumber); + Product getProduct(Integer id); + Product save(ProductModel productModel); + Product update(Integer productId, ProductModel productModel); + +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/OrderRepositoryImpl.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/OrderRepositoryImpl.java new file mode 100644 index 0000000000..e4f316c865 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/OrderRepositoryImpl.java @@ -0,0 +1,36 @@ +package com.baeldung.graphqlvsrest.repository.impl; + +import com.baeldung.graphqlvsrest.entity.Order; +import com.baeldung.graphqlvsrest.repository.OrderRepository; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Repository +public class OrderRepositoryImpl implements OrderRepository { + + private static List orderList = new ArrayList<>(); + + public OrderRepositoryImpl() { + for (int i = 1; i <= 100; i++){ + Order order = new Order(); + order.setId(i); + order.setProduct_id(i%10); + order.setAddress(UUID.randomUUID().toString()); + order.setCustomer_uuid(UUID.randomUUID().toString()); + order.setCreation_date(new Date(System.currentTimeMillis()).toString()); + order.setStatus("Delivered"); + orderList.add(order); + } + } + + + @Override + public List getOrdersByProduct(Integer productId) { + return orderList.stream().filter(order -> order.getProduct_id().equals(productId)).collect(Collectors.toList()); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/ProductRepositoryImpl.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/ProductRepositoryImpl.java new file mode 100644 index 0000000000..845472faea --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/repository/impl/ProductRepositoryImpl.java @@ -0,0 +1,74 @@ +package com.baeldung.graphqlvsrest.repository.impl; + +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Repository +public class ProductRepositoryImpl implements ProductRepository { + + private static List productList = new ArrayList<>(); + + public ProductRepositoryImpl() { + for (int i = 1; i <= 10; i++){ + Product product = new Product(); + product.setId(i); + product.setName(String.format("Product %d", i)); + product.setDescription(String.format("Product %d description", i)); + product.setCurrency(String.format("Product %d currency", i)); + product.setPrice(Double.valueOf(i^2)); + product.setStock(10); + product.setAverage_rating(0F); + product.setImage_url(Arrays.asList(String.format("www.baeldung.com/imageurl/%d", i))); + product.setVideo_url(Arrays.asList(String.format("www.baeldung.com/videourl/%d", i))); + productList.add(product); + } + } + + @Override + public List getProducts(Integer pageSize, Integer pageNumber) { + return productList.stream().skip(pageSize*pageNumber).limit(pageSize).collect(Collectors.toList()); + } + + @Override + public Product getProduct(Integer id) { + return productList.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null); + } + + @Override + public Product save(ProductModel productModel) { + Product product = new Product(productList.size()+1, productModel); + productList.add(product); + return product; + } + + @Override + public Product update(Integer productId, ProductModel productModel) { + Product product = getProduct(productId); + if (product != null){ + update(product, productModel); + } + return product; + } + + private void update(Product product, ProductModel productModel){ + if (productModel != null) { + System.out.println(productModel.toString()); + Optional.ofNullable(productModel.getName()).ifPresent(product::setName); + Optional.ofNullable(productModel.getDescription()).ifPresent(product::setDescription); + Optional.ofNullable(productModel.getCurrency()).ifPresent(product::setCurrency); + Optional.ofNullable(productModel.getImage_url()).ifPresent(product::setImage_url); + Optional.ofNullable(productModel.getStock()).ifPresent(product::setStock); + Optional.ofNullable(productModel.getStatus()).ifPresent(product::setStatus); + Optional.ofNullable(productModel.getVideo_url()).ifPresent(product::setVideo_url); + Optional.ofNullable(productModel.getPrice()).ifPresent(product::setPrice); + } + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Mutation.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Mutation.java new file mode 100644 index 0000000000..3d643f97e6 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Mutation.java @@ -0,0 +1,22 @@ +package com.baeldung.graphqlvsrest.resolver; + +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.model.ProductModel; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import com.coxautodev.graphql.tools.GraphQLMutationResolver; + +public class Mutation implements GraphQLMutationResolver { + + private ProductRepository productRepository; + public Mutation(ProductRepository productRepository){ + this.productRepository = productRepository; + } + + public Product saveProduct(ProductModel productModel) { + return productRepository.save(productModel); + } + + public Product updateProduct(Integer productId, ProductModel productModel) { + return productRepository.update(productId, productModel); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/ProductResolver.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/ProductResolver.java new file mode 100644 index 0000000000..f20b8d5920 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/ProductResolver.java @@ -0,0 +1,18 @@ +package com.baeldung.graphqlvsrest.resolver; + +import com.baeldung.graphqlvsrest.entity.Order; +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.repository.OrderRepository; +import com.coxautodev.graphql.tools.GraphQLResolver; + +import java.util.List; + +public class ProductResolver implements GraphQLResolver { + private OrderRepository orderRepository; + public ProductResolver(OrderRepository orderRepository){ + this.orderRepository = orderRepository; + } + public List getOrders(Product product){ + return orderRepository.getOrdersByProduct(product.getId()); + } +} diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Query.java b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Query.java new file mode 100644 index 0000000000..0d218261b2 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/java/com/baeldung/graphqlvsrest/resolver/Query.java @@ -0,0 +1,27 @@ +package com.baeldung.graphqlvsrest.resolver; + +import com.baeldung.graphqlvsrest.entity.Order; +import com.baeldung.graphqlvsrest.entity.Product; +import com.baeldung.graphqlvsrest.repository.OrderRepository; +import com.baeldung.graphqlvsrest.repository.ProductRepository; +import com.coxautodev.graphql.tools.GraphQLQueryResolver; + +import java.util.List; + +public class Query implements GraphQLQueryResolver { + + private ProductRepository productRepository; + public Query(ProductRepository productRepository){ + this.productRepository = productRepository; + } + + public List getProducts(int pageSize, int pageNumber) { + return productRepository.getProducts(pageSize, pageNumber); + } + + public Product getProduct(int id) { + return productRepository.getProduct(id); + } + + +} diff --git a/guest/slf4j/guide/slf4j-log4j/src/main/resources/application.properties b/spring-boot-modules/spring-boot-libraries-comparison/src/main/resources/application.properties similarity index 100% rename from guest/slf4j/guide/slf4j-log4j/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-libraries-comparison/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-boot-libraries-comparison/src/main/resources/graphql/schema.graphqls b/spring-boot-modules/spring-boot-libraries-comparison/src/main/resources/graphql/schema.graphqls new file mode 100644 index 0000000000..2709510d72 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-comparison/src/main/resources/graphql/schema.graphqls @@ -0,0 +1,57 @@ +type Product { + id: ID + name: String! + description: String + status: String + currency: String! + price: Float + image_url: [String] + video_url: [String] + stock: Int + average_rating: Float + orders:[Order] +} + +type Order{ + id:ID + product_id:Int + customer_uuid:String + address:String + status:String + creation_date:String +} + +input ProductModel { + name: String! + description: String + status: String + currency: String! + price: Float + image_url: [String] + video_url: [String] + stock: Int +} + +input ProductUpdateModel { + name: String + description: String + status: String + currency: String + price: Float + image_url: [String] + video_url: [String] + stock: Int +} + + +# The Root Query for the application +type Query { + products(size: Int, page: Int): [Product]! + product(id: Int): Product! +} + +# The Root Mutation for the application +type Mutation { + saveProduct(product: ProductModel) : Product! + updateProduct(id: Int, product: ProductUpdateModel) : Product! +} diff --git a/spring-boot-modules/spring-boot-libraries/README.md b/spring-boot-modules/spring-boot-libraries/README.md index 6976435866..b72815e4a9 100644 --- a/spring-boot-modules/spring-boot-libraries/README.md +++ b/spring-boot-modules/spring-boot-libraries/README.md @@ -14,7 +14,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Boot and Caffeine Cache](https://www.baeldung.com/spring-boot-caffeine-cache) - [Spring Boot and Togglz Aspect](https://www.baeldung.com/spring-togglz) - [Getting Started with GraphQL and Spring Boot](https://www.baeldung.com/spring-graphql) -- [An Introduction to Kong](https://www.baeldung.com/kong) +- More articles: [[next -->]](/spring-boot-modules/spring-boot-libraries-2) ### GraphQL sample queries diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml index ad00629e14..db467a8de5 100644 --- a/spring-boot-modules/spring-boot-libraries/pom.xml +++ b/spring-boot-modules/spring-boot-libraries/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -83,7 +82,6 @@ com.h2database h2 - ${h2.version} @@ -236,11 +234,9 @@ 2.0.0 5.0.2 5.2.4 - 18.0 2.2.4 2.3.2 0.23.0 - 1.4.200 2.1.0 1.5-beta1 2.1 diff --git a/spring-boot-modules/spring-boot-logging-log4j2/pom.xml b/spring-boot-modules/spring-boot-logging-log4j2/pom.xml index dafbddb93f..8cf052deb3 100644 --- a/spring-boot-modules/spring-boot-logging-log4j2/pom.xml +++ b/spring-boot-modules/spring-boot-logging-log4j2/pom.xml @@ -18,8 +18,8 @@ - + junit junit diff --git a/spring-boot-modules/spring-boot-multiple-datasources/.gitignore b/spring-boot-modules/spring-boot-multiple-datasources/.gitignore new file mode 100644 index 0000000000..87a3fce287 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/.gitignore @@ -0,0 +1 @@ +.local-db diff --git a/spring-boot-modules/spring-boot-multiple-datasources/pom.xml b/spring-boot-modules/spring-boot-multiple-datasources/pom.xml new file mode 100644 index 0000000000..d66095bc2c --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + spring-boot-multiple-datasources + 0.1.0-SNAPSHOT + spring-boot-multiple-datasources + jar + Module For Spring Boot With Multiple Datasources + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../pom.xml + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + provided + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 2.6.3 + + + diff --git a/guest/remote-debugging/src/main/java/com/stackify/debug/JavaRemoteDebuggingApplication.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java similarity index 58% rename from guest/remote-debugging/src/main/java/com/stackify/debug/JavaRemoteDebuggingApplication.java rename to spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java index 9d1a632638..efdff387df 100644 --- a/guest/remote-debugging/src/main/java/com/stackify/debug/JavaRemoteDebuggingApplication.java +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java @@ -1,12 +1,13 @@ -package com.stackify.debug; +package com.baeldung.spring.datasources; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class JavaRemoteDebuggingApplication { +public class MultipleDatasourcesApplication { public static void main(String[] args) { - SpringApplication.run(JavaRemoteDebuggingApplication.class, args); + SpringApplication.run(MultipleDatasourcesApplication.class, args); } + } diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/Todo.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/Todo.java new file mode 100644 index 0000000000..6f8557e258 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/Todo.java @@ -0,0 +1,48 @@ +package com.baeldung.spring.datasources.todos; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Todo { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String title; + private boolean completed; + + public Todo() { + } + + public Todo(String title) { + this.title = title; + } + + 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 boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoDatasourceConfiguration.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoDatasourceConfiguration.java new file mode 100644 index 0000000000..3bfc8e2855 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoDatasourceConfiguration.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.datasources.todos; + +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import javax.sql.DataSource; + +@Configuration +public class TodoDatasourceConfiguration { + + @Bean + @ConfigurationProperties("spring.datasource.todos") + public DataSourceProperties todosDataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + @Primary + public DataSource todosDataSource() { + return todosDataSourceProperties() + .initializeDataSourceBuilder() + .build(); + } + +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoJpaConfiguration.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoJpaConfiguration.java new file mode 100644 index 0000000000..655a3a55c2 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoJpaConfiguration.java @@ -0,0 +1,40 @@ +package com.baeldung.spring.datasources.todos; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + basePackageClasses = Todo.class, + entityManagerFactoryRef = "todosEntityManagerFactory", + transactionManagerRef = "todosTransactionManager" +) +public class TodoJpaConfiguration { + + @Bean + public LocalContainerEntityManagerFactoryBean todosEntityManagerFactory( + @Qualifier("todosDataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder) { + return builder + .dataSource(dataSource) + .packages(Todo.class) + .build(); + } + + @Bean + public PlatformTransactionManager todosTransactionManager( + @Qualifier("todosEntityManagerFactory") LocalContainerEntityManagerFactoryBean todosEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(todosEntityManagerFactory.getObject())); + } +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoRepository.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoRepository.java new file mode 100644 index 0000000000..09fb8c6500 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/todos/TodoRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.spring.datasources.todos; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TodoRepository extends JpaRepository { +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/Topic.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/Topic.java new file mode 100644 index 0000000000..1d1f20f111 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/Topic.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.datasources.topics; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Topic { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String title; + + public Topic() { + } + + public Topic(String title) { + this.title = title; + } + + 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; + } + +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicDatasourceConfiguration.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicDatasourceConfiguration.java new file mode 100644 index 0000000000..a06983d681 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicDatasourceConfiguration.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.datasources.topics; + +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class TopicDatasourceConfiguration { + + @Bean + @ConfigurationProperties("spring.datasource.topics") + public DataSourceProperties topicsDataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + public DataSource topicsDataSource() { + return topicsDataSourceProperties() + .initializeDataSourceBuilder() + .build(); + } + +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicJpaConfiguration.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicJpaConfiguration.java new file mode 100644 index 0000000000..d800813b8c --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicJpaConfiguration.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.datasources.topics; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + basePackageClasses = Topic.class, + entityManagerFactoryRef = "topicsEntityManagerFactory", + transactionManagerRef = "topicsTransactionManager" +) +public class TopicJpaConfiguration { + + @Bean + public LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory( + @Qualifier("topicsDataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder + ) { + return builder + .dataSource(dataSource) + .packages(Topic.class) + .build(); + } + + @Bean + public PlatformTransactionManager topicsTransactionManager( + @Qualifier("topicsEntityManagerFactory") LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(topicsEntityManagerFactory.getObject())); + } +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicRepository.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicRepository.java new file mode 100644 index 0000000000..499b72650a --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/topics/TopicRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.spring.datasources.topics; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TopicRepository extends JpaRepository { +} diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/main/resources/application.yml b/spring-boot-modules/spring-boot-multiple-datasources/src/main/resources/application.yml new file mode 100644 index 0000000000..4754acfc0f --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/resources/application.yml @@ -0,0 +1,23 @@ +spring: + datasource: + todos: + url: jdbc:h2:./.local-db/todos;DB_CLOSE_DELAY=-1;MODE=DB2;AUTO_SERVER=TRUE + username: sa + password: null + driverClassName: org.h2.Driver + topics: + url: jdbc:h2:./.local-db/topics;DB_CLOSE_DELAY=-1;MODE=DB2;AUTO_SERVER=TRUE + username: sa + password: null + driverClassName: org.h2.Driver + h2: + console: + enabled: true + path: /h2-console + jpa: + generate-ddl: true + hibernate: + ddl-auto: update + properties: + hibernate: + dialect: org.hibernate.dialect.H2Dialect diff --git a/spring-boot-modules/spring-boot-multiple-datasources/src/test/java/com/baeldung/spring/datasources/MultipleDatasourcesIntegrationTest.java b/spring-boot-modules/spring-boot-multiple-datasources/src/test/java/com/baeldung/spring/datasources/MultipleDatasourcesIntegrationTest.java new file mode 100644 index 0000000000..397992f6c8 --- /dev/null +++ b/spring-boot-modules/spring-boot-multiple-datasources/src/test/java/com/baeldung/spring/datasources/MultipleDatasourcesIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.datasources; + +import com.baeldung.spring.datasources.todos.Todo; +import com.baeldung.spring.datasources.todos.TodoRepository; +import com.baeldung.spring.datasources.topics.Topic; +import com.baeldung.spring.datasources.topics.TopicRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest // no test database! +class MultipleDatasourcesIntegrationTest { + + @Autowired + TodoRepository todoRepo; + @Autowired + TopicRepository topicRepo; + + @Test + void shouldSaveTodoToTodoDB() { + Todo todo = new Todo("test"); + Todo saved =todoRepo.save(todo); + Optional result= todoRepo.findById(saved.getId()); + assertThat(result).isPresent(); + } + + @Test + void shouldSaveTopicToTopicDB() { + Topic todo = new Topic("test"); + Topic saved =topicRepo.save(todo); + Optional result= topicRepo.findById(saved.getId()); + assertThat(result).isPresent(); + } + +} diff --git a/spring-boot-modules/spring-boot-mvc-2/README.md b/spring-boot-modules/spring-boot-mvc-2/README.md index f9becb721f..0d0e05daf0 100644 --- a/spring-boot-modules/spring-boot-mvc-2/README.md +++ b/spring-boot-modules/spring-boot-mvc-2/README.md @@ -7,7 +7,6 @@ This module contains articles about Spring Web MVC in Spring Boot projects. - [Functional Controllers in Spring MVC](https://www.baeldung.com/spring-mvc-functional-controllers) - [Specify an Array of Strings as Body Parameters in Swagger](https://www.baeldung.com/swagger-body-array-of-strings) - [Swagger @ApiParam vs @ApiModelProperty](https://www.baeldung.com/swagger-apiparam-vs-apimodelproperty) -- [ETags for REST with Spring](https://www.baeldung.com/etags-for-rest-with-spring) - [Testing REST with multiple MIME types](https://www.baeldung.com/testing-rest-api-with-multiple-media-types) - [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) - [Spring Boot Consuming and Producing JSON](https://www.baeldung.com/spring-boot-json) diff --git a/spring-boot-modules/spring-boot-mvc-2/pom.xml b/spring-boot-modules/spring-boot-mvc-2/pom.xml index d347b36b3b..f303171df8 100644 --- a/spring-boot-modules/spring-boot-mvc-2/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-2/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/Foo.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/Foo.java new file mode 100644 index 0000000000..a8e379fc79 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/Foo.java @@ -0,0 +1,93 @@ +package com.baeldung.mime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Version; +import java.io.Serializable; + +@Entity +public class Foo implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + @Version + private long version; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java new file mode 100644 index 0000000000..d7da9bd849 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java @@ -0,0 +1,36 @@ +package com.baeldung.mime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import javax.servlet.http.HttpServletResponse; + +@RestController +@RequestMapping(value = "/foos") +public class FooController { + + @Autowired + private FooDao fooDao; + + @GetMapping(value = "/{id}") + public Foo findById(@PathVariable("id") final Long id, final HttpServletResponse response) { + return fooDao.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { + return fooDao.save(resource); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooDao.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooDao.java new file mode 100644 index 0000000000..9fc99e1124 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooDao.java @@ -0,0 +1,8 @@ +package com.baeldung.mime; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FooDao extends CrudRepository{ +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/FooLiveTest.java b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/FooLiveTest.java index e65b106ead..86dd4915b4 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/FooLiveTest.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/FooLiveTest.java @@ -14,15 +14,12 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.baeldung.etag.Foo; -import com.baeldung.etag.WebConfig; - import io.restassured.RestAssured; import io.restassured.response.Response; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes= WebConfig.class, webEnvironment = WebEnvironment.RANDOM_PORT) -@ComponentScan({"com.baeldung.mime", "com.baeldung.etag"}) +@SpringBootTest(classes = FooController.class, webEnvironment = WebEnvironment.RANDOM_PORT) +@ComponentScan({"com.baeldung.mime"}) @EnableAutoConfiguration @ActiveProfiles("test") public class FooLiveTest { @@ -47,12 +44,12 @@ public class FooLiveTest { createAsUri(resource); } - private final String createAsUri(final Foo resource) { + private String createAsUri(final Foo resource) { final Response response = createAsResponse(resource); return getURL() + "/" + response.getBody().as(Foo.class).getId(); } - private final Response createAsResponse(final Foo resource) { + private Response createAsResponse(final Foo resource) { final String resourceAsString = marshaller.encode(resource); return RestAssured.given() diff --git a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/JacksonMarshaller.java b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/JacksonMarshaller.java index 9dee0ef2cd..c6d14a9427 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/JacksonMarshaller.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/JacksonMarshaller.java @@ -7,7 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; -import com.baeldung.etag.Foo; +import com.baeldung.mime.Foo; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/XStreamMarshaller.java b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/XStreamMarshaller.java index 2c67694e83..8a4188ceca 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/XStreamMarshaller.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/mime/XStreamMarshaller.java @@ -4,7 +4,7 @@ import java.util.List; import org.springframework.http.MediaType; -import com.baeldung.etag.Foo; +import com.baeldung.mime.Foo; import com.thoughtworks.xstream.XStream; public final class XStreamMarshaller implements IMarshaller { diff --git a/spring-boot-modules/spring-boot-mvc-3/README.md b/spring-boot-modules/spring-boot-mvc-3/README.md index f9c6989b3c..fa24ac11ed 100644 --- a/spring-boot-modules/spring-boot-mvc-3/README.md +++ b/spring-boot-modules/spring-boot-mvc-3/README.md @@ -10,4 +10,5 @@ This module contains articles about Spring Web MVC in Spring Boot projects. - [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) - [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) - [HandlerInterceptors vs. Filters in Spring MVC](https://www.baeldung.com/spring-mvc-handlerinterceptor-vs-filter) +- [ETags for REST with Spring](https://www.baeldung.com/etags-for-rest-with-spring) - More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-boot-modules/spring-boot-mvc-3/pom.xml b/spring-boot-modules/spring-boot-mvc-3/pom.xml index a46837e315..43a492786e 100644 --- a/spring-boot-modules/spring-boot-mvc-3/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-3/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-mvc-3 - jar spring-boot-mvc-3 + jar Module For Spring Boot MVC Web com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -28,6 +27,14 @@ org.springframework.boot spring-boot-starter-thymeleaf + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + commons-io commons-io diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/Foo.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/Foo.java similarity index 99% rename from spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/Foo.java rename to spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/Foo.java index e553ca1b72..9790bca663 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/Foo.java +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/Foo.java @@ -1,13 +1,12 @@ package com.baeldung.etag; -import java.io.Serializable; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Version; +import java.io.Serializable; @Entity public class Foo implements Serializable { diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/FooController.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/FooController.java similarity index 99% rename from spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/FooController.java rename to spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/FooController.java index 58f366501d..d40a5e7809 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/FooController.java +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/FooController.java @@ -1,7 +1,5 @@ package com.baeldung.etag; -import javax.servlet.http.HttpServletResponse; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,6 +14,8 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; +import javax.servlet.http.HttpServletResponse; + @RestController @RequestMapping(value = "/foos") public class FooController { diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/FooDao.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/FooDao.java similarity index 100% rename from spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/FooDao.java rename to spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/FooDao.java diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/SpringBootEtagApplication.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/SpringBootEtagApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/SpringBootEtagApplication.java rename to spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/SpringBootEtagApplication.java diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/WebConfig.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/WebConfig.java similarity index 100% rename from spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/etag/WebConfig.java rename to spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/etag/WebConfig.java diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java new file mode 100644 index 0000000000..14908ae108 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/CompareApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.micronaut.vs.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@EnableAutoConfiguration +@ComponentScan("com.baeldung.micronaut.vs.springboot") +public class CompareApplication { + public static void main(final String[] args) { + SpringApplication.run(CompareApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java new file mode 100644 index 0000000000..54b2680dca --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticController.java @@ -0,0 +1,61 @@ +package com.baeldung.micronaut.vs.springboot.controller; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.micronaut.vs.springboot.service.ArithmeticService; + +@RestController +@RequestMapping("/math") +public class ArithmeticController { + @Autowired + private ArithmeticService arithmeticService; + + @GetMapping("/sum/{number1}/{number2}") + public float getSum(@PathVariable("number1") float number1, @PathVariable("number2") float number2) { + return arithmeticService.add(number1, number2); + } + + @GetMapping("/subtract/{number1}/{number2}") + public float getDifference(@PathVariable("number1") float number1, @PathVariable("number2") float number2) { + return arithmeticService.subtract(number1, number2); + } + + @GetMapping("/multiply/{number1}/{number2}") + public float getMultiplication(@PathVariable("number1") float number1, @PathVariable("number2") float number2) { + return arithmeticService.multiply(number1, number2); + } + + @GetMapping("/divide/{number1}/{number2}") + public float getDivision(@PathVariable("number1") float number1, @PathVariable("number2") float number2) { + return arithmeticService.divide(number1, number2); + } + + @GetMapping("/memory") + public String getMemoryStatus() { + MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); + String memoryStats = ""; + + String init = String.format( + "Initial: %.2f GB \n", + (double)memoryBean.getHeapMemoryUsage().getInit() /1073741824); + String usedHeap = String.format("Used: %.2f GB \n", + (double)memoryBean.getHeapMemoryUsage().getUsed() /1073741824); + String maxHeap = String.format("Max: %.2f GB \n", + (double)memoryBean.getHeapMemoryUsage().getMax() /1073741824); + String committed = String.format("Committed: %.2f GB \n", + (double)memoryBean.getHeapMemoryUsage().getCommitted() /1073741824); + memoryStats += init; + memoryStats += usedHeap; + memoryStats += maxHeap; + memoryStats += committed; + + return memoryStats; + } +} diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java new file mode 100644 index 0000000000..0ed84b63c5 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/micronaut/vs/springboot/service/ArithmeticService.java @@ -0,0 +1,25 @@ +package com.baeldung.micronaut.vs.springboot.service; + +import org.springframework.stereotype.Service; + +@Service +public class ArithmeticService { + public float add(float number1, float number2) { + return number1 + number2; + } + + public float subtract(float number1, float number2) { + return number1 - number2; + } + + public float multiply(float number1, float number2) { + return number1 * number2; + } + + public float divide(float number1, float number2) { + if (number2 == 0) { + throw new IllegalArgumentException("'number2' cannot be zero"); + } + return number1 / number2; + } +} diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/resources/WEB-INF/web.xml b/spring-boot-modules/spring-boot-mvc-3/src/main/resources/WEB-INF/web.xml similarity index 100% rename from spring-boot-modules/spring-boot-mvc-2/src/main/resources/WEB-INF/web.xml rename to spring-boot-modules/spring-boot-mvc-3/src/main/resources/WEB-INF/web.xml diff --git a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/etag/EtagIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java similarity index 99% rename from spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/etag/EtagIntegrationTest.java rename to spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java index 88c5ae1686..97de6d06f1 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/test/java/com/baeldung/etag/EtagIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java @@ -1,10 +1,10 @@ package com.baeldung.etag; -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.Response; import org.assertj.core.util.Preconditions; import org.junit.Ignore; import org.junit.Test; @@ -18,12 +18,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import io.restassured.response.Response; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) diff --git a/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticControllerUnitTest.java b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticControllerUnitTest.java new file mode 100644 index 0000000000..6b08bfbd9c --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/micronaut/vs/springboot/controller/ArithmeticControllerUnitTest.java @@ -0,0 +1,68 @@ +package com.baeldung.micronaut.vs.springboot.controller; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.Test; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.hamcrest.Matchers.containsString; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import com.baeldung.micronaut.vs.springboot.CompareApplication; + +@SpringBootTest(classes = CompareApplication.class) +@AutoConfigureMockMvc +public class ArithmeticControllerUnitTest { + @Autowired + private MockMvc mockMvc; + + @Test + public void givenTwoNumbers_whenAdd_thenCorrectAnswerReturned() throws Exception { + Float expected = Float.valueOf(10 + 20); + this.mockMvc.perform(MockMvcRequestBuilders.get("/math/sum/10/20") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(expected.toString())); + } + + @Test + public void givenTwoNumbers_whenSubtract_thenCorrectAnswerReturned() throws Exception { + Float expected = Float.valueOf(20 - 10); + this.mockMvc.perform(MockMvcRequestBuilders.get("/math/subtract/20/10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(expected.toString())); + } + + @Test + public void givenTwoNumbers_whenMultiply_thenCorrectAnswerReturned() throws Exception { + Float expected = Float.valueOf(20 * 10); + this.mockMvc.perform(MockMvcRequestBuilders.get("/math/multiply/20/10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(expected.toString())); + } + + @Test + public void givenTwoNumbers_whenDivide_thenCorrectAnswerReturned() throws Exception { + Float expected = Float.valueOf(20 / 10); + this.mockMvc.perform(MockMvcRequestBuilders.get("/math/divide/20/10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(expected.toString())); + } + + @Test + public void whenMemory_thenMemoryStringReturned() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/math/memory") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("Initial:"))); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-jersey/pom.xml b/spring-boot-modules/spring-boot-mvc-jersey/pom.xml index b6e2c62663..34b459d1dc 100644 --- a/spring-boot-modules/spring-boot-mvc-jersey/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-jersey/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/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/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-jersey/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/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/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-jersey/spring-boot-mvc/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/pom.xml b/spring-boot-modules/spring-boot-mvc/pom.xml index 3e835691aa..6d3f722146 100644 --- a/spring-boot-modules/spring-boot-mvc/pom.xml +++ b/spring-boot-modules/spring-boot-mvc/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties index 7f399bb11d..aea61842d2 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties @@ -1 +1,2 @@ -spring.thymeleaf.view-names=thymeleaf/* \ No newline at end of file +spring.thymeleaf.view-names=thymeleaf/* +spring.mvc.pathmatch.matching-strategy=ant-path-matcher \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-nashorn/pom.xml b/spring-boot-modules/spring-boot-nashorn/pom.xml index 89b0b984bc..0ae108ffd0 100644 --- a/spring-boot-modules/spring-boot-nashorn/pom.xml +++ b/spring-boot-modules/spring-boot-nashorn/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-parent/pom.xml b/spring-boot-modules/spring-boot-parent/pom.xml index 28a940bcd0..d9c23b66ac 100644 --- a/spring-boot-modules/spring-boot-parent/pom.xml +++ b/spring-boot-modules/spring-boot-parent/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml b/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml index a61a5fd057..18fa4c53d9 100644 --- a/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml +++ b/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-parent 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml b/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml index 2568714278..e65f590c9b 100644 --- a/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml +++ b/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-parent 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-performance/pom.xml b/spring-boot-modules/spring-boot-performance/pom.xml index f1f9b52dc4..38f5758c1f 100644 --- a/spring-boot-modules/spring-boot-performance/pom.xml +++ b/spring-boot-modules/spring-boot-performance/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-properties-2/README.md b/spring-boot-modules/spring-boot-properties-2/README.md index c81ad50e40..501beed092 100644 --- a/spring-boot-modules/spring-boot-properties-2/README.md +++ b/spring-boot-modules/spring-boot-properties-2/README.md @@ -3,7 +3,6 @@ This module contains articles about Properties in Spring Boot. ### Relevant Articles: -- [Load Spring Boot Properties From a JSON File](https://www.baeldung.com/spring-boot-json-properties) - [A Quick Guide to Spring @Value](https://www.baeldung.com/spring-value-annotation) - [Using Spring @Value with Defaults](https://www.baeldung.com/spring-value-defaults) - [How to Inject a Property Value Into a Class Not Managed by Spring?](https://www.baeldung.com/inject-properties-value-non-spring-class) diff --git a/spring-boot-modules/spring-boot-properties-2/pom.xml b/spring-boot-modules/spring-boot-properties-2/pom.xml index 62f23da450..442cb24c7a 100644 --- a/spring-boot-modules/spring-boot-properties-2/pom.xml +++ b/spring-boot-modules/spring-boot-properties-2/pom.xml @@ -4,16 +4,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-properties-2 - jar 0.0.1-SNAPSHOT spring-boot-properties-2 + jar Spring Boot Properties Module com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-properties-2/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-properties-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties-3/README.md b/spring-boot-modules/spring-boot-properties-3/README.md index df272be7f4..1bd6724885 100644 --- a/spring-boot-modules/spring-boot-properties-3/README.md +++ b/spring-boot-modules/spring-boot-properties-3/README.md @@ -7,3 +7,5 @@ - [How to Define a Map in YAML for a POJO?](https://www.baeldung.com/yaml-map-pojo) - [Using application.yml vs application.properties in Spring Boot](https://www.baeldung.com/spring-boot-yaml-vs-properties) +- [Load Spring Boot Properties From a JSON File](https://www.baeldung.com/spring-boot-json-properties) +- [IntelliJ – Cannot Resolve Spring Boot Configuration Properties Error](https://www.baeldung.com/intellij-resolve-spring-boot-configuration-properties) \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties-3/pom.xml b/spring-boot-modules/spring-boot-properties-3/pom.xml index b5e6ef8701..d72c410d9b 100644 --- a/spring-boot-modules/spring-boot-properties-3/pom.xml +++ b/spring-boot-modules/spring-boot-properties-3/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/CustomProperties.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/CustomProperties.java similarity index 83% rename from spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/CustomProperties.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/CustomProperties.java index 398b7557c4..2b6ff560b3 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/CustomProperties.java +++ b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/CustomProperties.java @@ -1,7 +1,7 @@ package com.baeldung.configuration.processor; -import org.springframework.boot.context.properties.*; -import org.springframework.context.annotation.*; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "com.baeldung") diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/DemoApplication.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/DemoApplication.java similarity index 64% rename from spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/DemoApplication.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/DemoApplication.java index 1a35de86da..44641a2caf 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/DemoApplication.java +++ b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/DemoApplication.java @@ -1,7 +1,7 @@ package com.baeldung.configuration.processor; -import org.springframework.boot.*; -import org.springframework.boot.autoconfigure.*; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java similarity index 65% rename from spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java index bbd193acba..5a4073e831 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java +++ b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/JdbcProperties.java @@ -1,8 +1,8 @@ package com.baeldung.configuration.processor; -import org.springframework.boot.context.properties.*; -import org.springframework.context.annotation.*; -import org.springframework.beans.factory.annotation.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "com.baeldung") diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java similarity index 85% rename from spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java index 89a8f9458c..66cec5b1cb 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java +++ b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/configuration/processor/PropertyBeanInjection.java @@ -1,7 +1,7 @@ package com.baeldung.configuration.processor; -import org.springframework.beans.factory.annotation.*; -import org.springframework.stereotype.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; @Component public class PropertyBeanInjection { diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/ConfigPropertiesDemoApplication.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/ConfigPropertiesDemoApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/ConfigPropertiesDemoApplication.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/ConfigPropertiesDemoApplication.java diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/CustomJsonProperties.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/CustomJsonProperties.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/CustomJsonProperties.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/CustomJsonProperties.java diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/JsonProperties.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/JsonProperties.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/JsonProperties.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/JsonProperties.java diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/JsonPropertyContextInitializer.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/JsonPropertyContextInitializer.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/JsonPropertyContextInitializer.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/JsonPropertyContextInitializer.java diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/factory/JsonPropertySourceFactory.java b/spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/factory/JsonPropertySourceFactory.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/json/factory/JsonPropertySourceFactory.java rename to spring-boot-modules/spring-boot-properties-3/src/main/java/com/baeldung/properties/json/factory/JsonPropertySourceFactory.java diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/resources/configprops.json b/spring-boot-modules/spring-boot-properties-3/src/main/resources/configprops.json similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/main/resources/configprops.json rename to spring-boot-modules/spring-boot-properties-3/src/main/resources/configprops.json diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/configuration-processor.properties b/spring-boot-modules/spring-boot-properties-3/src/main/resources/configuration-processor.properties similarity index 100% rename from spring-boot-modules/spring-boot-properties/src/main/resources/configuration-processor.properties rename to spring-boot-modules/spring-boot-properties-3/src/main/resources/configuration-processor.properties diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java similarity index 68% rename from spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java rename to spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java index eb6add2b94..5204f06e88 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/configuration/processor/PropertyBeanInjectionUnitTest.java @@ -1,11 +1,12 @@ package com.baeldung.configuration.processor; -import org.junit.jupiter.api.*; -import org.junit.runner.*; -import org.springframework.beans.factory.annotation.*; -import org.springframework.boot.test.context.*; -import org.springframework.test.context.*; -import org.springframework.test.context.junit4.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.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.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @TestPropertySource("/configuration-processor.properties") diff --git a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/json/JsonPropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/properties/json/JsonPropertiesIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/json/JsonPropertiesIntegrationTest.java rename to spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/properties/json/JsonPropertiesIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/configuration-processor.properties b/spring-boot-modules/spring-boot-properties-3/src/test/resources/configuration-processor.properties similarity index 100% rename from spring-boot-modules/spring-boot-properties/src/test/resources/configuration-processor.properties rename to spring-boot-modules/spring-boot-properties-3/src/test/resources/configuration-processor.properties diff --git a/spring-boot-modules/spring-boot-properties/README.md b/spring-boot-modules/spring-boot-properties/README.md index db96c63b29..2c899b5836 100644 --- a/spring-boot-modules/spring-boot-properties/README.md +++ b/spring-boot-modules/spring-boot-properties/README.md @@ -9,6 +9,5 @@ This module contains articles about Properties in Spring Boot. - [Properties with Spring and Spring Boot](https://www.baeldung.com/properties-with-spring) - checkout the `com.baeldung.properties` package for all scenarios of properties injection and usage - [Spring YAML Configuration](https://www.baeldung.com/spring-yaml) - [Add Build Properties to a Spring Boot Application](https://www.baeldung.com/spring-boot-build-properties) -- [IntelliJ – Cannot Resolve Spring Boot Configuration Properties Error](https://www.baeldung.com/intellij-resolve-spring-boot-configuration-properties) - [Spring YAML vs Properties](https://www.baeldung.com/spring-yaml-vs-properties) - More articles: [[more -->]](../spring-boot-properties-2) diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml index 0ef44e0546..41baf3bb82 100644 --- a/spring-boot-modules/spring-boot-properties/pom.xml +++ b/spring-boot-modules/spring-boot-properties/pom.xml @@ -4,16 +4,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-properties - jar 0.0.1-SNAPSHOT spring-boot-properties + jar Spring Boot Properties Module com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -123,9 +122,8 @@ - 2020.0.3 + 2021.0.0 1.10 - 20.0 @ com.baeldung.yaml.MyApplication diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/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/spring-boot-modules/spring-boot-properties/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-properties/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-property-exp/property-exp-default-config/pom.xml b/spring-boot-modules/spring-boot-property-exp/property-exp-default-config/pom.xml index 496004b0e2..b1c44de9a9 100644 --- a/spring-boot-modules/spring-boot-property-exp/property-exp-default-config/pom.xml +++ b/spring-boot-modules/spring-boot-property-exp/property-exp-default-config/pom.xml @@ -9,10 +9,9 @@ jar - com.baeldung - parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-property-exp 0.0.1-SNAPSHOT - ../../../parent-boot-2 diff --git a/spring-boot-modules/spring-boot-react/pom.xml b/spring-boot-modules/spring-boot-react/pom.xml index 3e8a9a7bd1..d515aed6ce 100644 --- a/spring-boot-modules/spring-boot-react/pom.xml +++ b/spring-boot-modules/spring-boot-react/pom.xml @@ -25,7 +25,6 @@ com.h2database h2 - ${h2.version} runtime @@ -128,7 +127,6 @@ v14.18.0 v1.12.1 2.4.4 - 1.4.200 1.0.2 diff --git a/spring-boot-modules/spring-boot-runtime-2/README.md b/spring-boot-modules/spring-boot-runtime-2/README.md index 9f0d814d8d..f439b0d0bd 100644 --- a/spring-boot-modules/spring-boot-runtime-2/README.md +++ b/spring-boot-modules/spring-boot-runtime-2/README.md @@ -4,3 +4,5 @@ This module contains articles about administering a Spring Boot runtime ### Relevant Articles: - [Configure the Heap Size When Starting a Spring Boot Application](https://www.baeldung.com/spring-boot-heap-size) + - [CORS with Spring](https://www.baeldung.com/spring-cors) + - [Max-HTTP-Header-Size in Spring Boot 2](https://www.baeldung.com/spring-boot-max-http-header-size) diff --git a/spring-boot-modules/spring-boot-runtime-2/pom.xml b/spring-boot-modules/spring-boot-runtime-2/pom.xml index c177529a41..5174900c79 100644 --- a/spring-boot-modules/spring-boot-runtime-2/pom.xml +++ b/spring-boot-modules/spring-boot-runtime-2/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-runtime-2 - jar spring-boot-runtime-2 + jar Demo project for Spring Boot com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -25,6 +24,10 @@ spring-boot-starter-test test + + org.springframework.security + spring-security-test + diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/Account.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/Account.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/Account.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/Account.java diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/AccountController.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/AccountController.java diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/config/WebConfig.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/config/WebConfig.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/config/WebConfig.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/cors/config/WebConfig.java diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/MaxHttpHeaderSizeApplication.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/MaxHttpHeaderSizeApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/MaxHttpHeaderSizeApplication.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/MaxHttpHeaderSizeApplication.java diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/config/MaxHTTPHeaderSizeConfig.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/config/MaxHTTPHeaderSizeConfig.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/config/MaxHTTPHeaderSizeConfig.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/config/MaxHTTPHeaderSizeConfig.java diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeController.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeController.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeController.java rename to spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeController.java diff --git a/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerIntegrationTest.java b/spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerIntegrationTest.java rename to spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerLiveTest.java b/spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerLiveTest.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerLiveTest.java rename to spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/maxhttpheadersize/controller/MaxHttpHeaderSizeControllerLiveTest.java diff --git a/spring-boot-modules/spring-boot-runtime/README.md b/spring-boot-modules/spring-boot-runtime/README.md index 072bd16a78..6f21efe793 100644 --- a/spring-boot-modules/spring-boot-runtime/README.md +++ b/spring-boot-modules/spring-boot-runtime/README.md @@ -8,7 +8,5 @@ This module contains articles about administering a Spring Boot runtime - [Logging HTTP Requests with Spring Boot Actuator HTTP Tracing](https://www.baeldung.com/spring-boot-actuator-http) - [Spring Boot Embedded Tomcat Logs](https://www.baeldung.com/spring-boot-embedded-tomcat-logs) - [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring) - - [CORS with Spring](https://www.baeldung.com/spring-cors) - [Spring – Log Incoming Requests](https://www.baeldung.com/spring-http-logging) - [How to Configure Spring Boot Tomcat](https://www.baeldung.com/spring-boot-configure-tomcat) - - [Max-HTTP-Header-Size in Spring Boot 2](https://www.baeldung.com/spring-boot-max-http-header-size) diff --git a/spring-boot-modules/spring-boot-runtime/pom.xml b/spring-boot-modules/spring-boot-runtime/pom.xml index 92b1458cf6..04c8ddc525 100644 --- a/spring-boot-modules/spring-boot-runtime/pom.xml +++ b/spring-boot-modules/spring-boot-runtime/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-runtime - jar spring-boot-runtime + jar Demo project for Spring Boot Runtime com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -94,9 +93,8 @@ 2.2 - 18.0 3.1.7 - 3.0.2 + 3.1.0 4.5.8 diff --git a/spring-boot-modules/spring-boot-security/README.md b/spring-boot-modules/spring-boot-security/README.md index 2c9d37eac0..b9966709cb 100644 --- a/spring-boot-modules/spring-boot-security/README.md +++ b/spring-boot-modules/spring-boot-security/README.md @@ -9,6 +9,7 @@ This module contains articles about Spring Boot Security - [Introduction to Spring Security Taglibs](https://www.baeldung.com/spring-security-taglibs) - [Guide to @CurrentSecurityContext in Spring Security](https://www.baeldung.com/spring-currentsecuritycontext) - [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile) +- [Spring @EnableWebSecurity vs. @EnableGlobalMethodSecurity](https://www.baeldung.com/spring-enablewebsecurity-vs-enableglobalmethodsecurity) ### Spring Boot Security Auto-Configuration diff --git a/spring-boot-modules/spring-boot-security/pom.xml b/spring-boot-modules/spring-boot-security/pom.xml index 11e5a38eeb..41dbcff38d 100644 --- a/spring-boot-modules/spring-boot-security/pom.xml +++ b/spring-boot-modules/spring-boot-security/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-security - jar spring-boot-security + jar Spring Boot Security Auto-Configuration com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/AntMatchersExampleApplication.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/AntMatchersExampleApplication.java new file mode 100644 index 0000000000..0a7828eff4 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/AntMatchersExampleApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.antmatchers; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AntMatchersExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(AntMatchersExampleApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/config/SecurityConfiguration.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/config/SecurityConfiguration.java new file mode 100644 index 0000000000..43e8c73bf0 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/config/SecurityConfiguration.java @@ -0,0 +1,39 @@ +package com.baeldung.antmatchers.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + public void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password(passwordEncoder().encode("password")).roles("USER", "ADMIN") + .and() + .withUser("user").password(passwordEncoder().encode("password")).roles("USER"); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/products/**").permitAll() + .and() + .authorizeRequests() + .antMatchers("/customers/**").hasRole("ADMIN") + .anyRequest().authenticated() + .and() + .httpBasic(); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/CustomerController.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/CustomerController.java new file mode 100644 index 0000000000..a031449797 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/CustomerController.java @@ -0,0 +1,15 @@ +package com.baeldung.antmatchers.controllers; + +import com.baeldung.antmatchers.dtos.Customer; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CustomerController { + + @GetMapping("/customers/{id}") + public Customer getCustomerById(@PathVariable("id") String id) { + return new Customer("Customer 1", "Address 1", "Phone 1"); + } +} diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/ProductController.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/ProductController.java new file mode 100644 index 0000000000..2968f3c025 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/controllers/ProductController.java @@ -0,0 +1,21 @@ +package com.baeldung.antmatchers.controllers; + +import com.baeldung.antmatchers.dtos.Product; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RestController +public class ProductController { + + @GetMapping("/products") + public List getProducts() { + return new ArrayList<>(Arrays.asList( + new Product("Product 1", "Description 1", 1.0), + new Product("Product 2", "Description 2", 2.0) + )); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Customer.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Customer.java new file mode 100644 index 0000000000..64bd95b095 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Customer.java @@ -0,0 +1,39 @@ +package com.baeldung.antmatchers.dtos; + +import java.io.Serializable; + +public class Customer implements Serializable { + private String name; + private String address; + private String phone; + + public Customer(String name, String address, String phone) { + this.name = name; + this.address = address; + this.phone = phone; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Product.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Product.java new file mode 100644 index 0000000000..84073ee8c0 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/antmatchers/dtos/Product.java @@ -0,0 +1,39 @@ +package com.baeldung.antmatchers.dtos; + +import java.io.Serializable; + +public class Product implements Serializable { + private String name; + private String description; + private double price; + + public Product(String name, String description, double price) { + this.name = name; + this.description = description; + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/CustomerControllerTest.java b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/CustomerControllerTest.java new file mode 100644 index 0000000000..de13dc0aea --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/CustomerControllerTest.java @@ -0,0 +1,38 @@ +package com.baeldung.antmatchers.controllers; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(value = CustomerController.class) +class CustomerControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void getCustomerByIdUnauthorized() throws Exception { + mockMvc.perform(get("/customers/1")).andExpect(status().isUnauthorized()); + } + + @Test + void getCustomerByIdForbidden() throws Exception { + mockMvc.perform(get("/customers/1").with(user("user").roles("USER"))) + .andExpect(status().isForbidden()); + } + + @Test + void getCustomerByIdOk() throws Exception { + mockMvc.perform(get("/customers/1").with(user("admin").roles("ADMIN"))) + .andExpect(status().isOk()); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/ProductControllerTest.java b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/ProductControllerTest.java new file mode 100644 index 0000000000..370e5f1597 --- /dev/null +++ b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/antmatchers/controllers/ProductControllerTest.java @@ -0,0 +1,25 @@ +package com.baeldung.antmatchers.controllers; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(value = ProductController.class) +class ProductControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void getProducts() throws Exception { + mockMvc.perform(get("/products")) + .andExpect(status().isOk()); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-springdoc/pom.xml b/spring-boot-modules/spring-boot-springdoc/pom.xml index 892fbfe4ca..d13efba450 100644 --- a/spring-boot-modules/spring-boot-springdoc/pom.xml +++ b/spring-boot-modules/spring-boot-springdoc/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-springdoc 0.0.1-SNAPSHOT - jar spring-boot-springdoc + jar Project for Springdoc integration com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -41,7 +40,6 @@ org.hibernate hibernate-core - ${hibernate.version} @@ -208,10 +206,9 @@ - 5.2.10.Final - 1.5.2 + 1.6.4 1.5.6 - 1.4.0 + 1.6.0 ${project.build.directory}/generated-snippets diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/resources/application.properties b/spring-boot-modules/spring-boot-springdoc/src/main/resources/application.properties index 0eecfbb1c4..733e716e76 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-springdoc/src/main/resources/application.properties @@ -10,5 +10,4 @@ spring.datasource.url=jdbc:h2:mem:springdoc ## for com.baeldung.restdocopenapi ## springdoc.version=@springdoc.version@ -spring.jpa.hibernate.ddl-auto=none -###################################### \ No newline at end of file +spring.jpa.hibernate.ddl-auto=none \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger-jwt/pom.xml b/spring-boot-modules/spring-boot-swagger-jwt/pom.xml index c296b06388..e0d96627cd 100644 --- a/spring-boot-modules/spring-boot-swagger-jwt/pom.xml +++ b/spring-boot-modules/spring-boot-swagger-jwt/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/README.md b/spring-boot-modules/spring-boot-swagger-keycloak/README.md new file mode 100644 index 0000000000..9c6513d9bf --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Keycloak Integration – OAuth2 and OpenID with Swagger UI](https://www.baeldung.com/keycloak-oauth2-openid-swagger) diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml b/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml new file mode 100644 index 0000000000..82e1951b8e --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + spring-boot-swagger-keycloak + 0.1.0-SNAPSHOT + spring-boot-swagger-keycloak + jar + Module For Spring Boot Swagger UI with Keycloak + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + + org.keycloak.bom + keycloak-adapter-bom + ${keycloak.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + io.springfox + springfox-boot-starter + ${springfox.version} + + + + org.keycloak + keycloak-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-security + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 2.4.5 + 3.0.0 + 15.0.2 + + + diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java new file mode 100644 index 0000000000..985cbf7d06 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java @@ -0,0 +1,59 @@ +package com.baeldung.swaggerkeycloak; + +import org.keycloak.adapters.springsecurity.KeycloakConfiguration; +import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; +import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; + +@KeycloakConfiguration +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class GlobalSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { + + @Override + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); + } + + // otherwise, we'll get an error 'permitAll only works with HttpSecurity.authorizeRequests()' + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + http + .csrf().disable() + .authorizeRequests() + // we can set up authorization here alternatively to @Secured methods + .antMatchers(HttpMethod.OPTIONS).permitAll() + .antMatchers("/api/**").authenticated() + // force authentication for all requests (and use global method security) + .anyRequest().permitAll(); + } + + /* + * re-configure Spring Security to use + * registers the KeycloakAuthenticationProvider with the authentication manager + */ + @Autowired + void configureGlobal(AuthenticationManagerBuilder auth) { + KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider(); + provider.setGrantedAuthoritiesMapper(authoritiesMapper()); + auth.authenticationProvider(provider); + } + + GrantedAuthoritiesMapper authoritiesMapper() { + SimpleAuthorityMapper mapper = new SimpleAuthorityMapper(); + mapper.setPrefix("ROLE_"); // Spring Security adds a prefix to the authority/role names (we use the default here) + mapper.setConvertToUpperCase(true); // convert names to uppercase + mapper.setDefaultAuthority("ROLE_ANONYMOUS"); // set a default authority + return mapper; + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/KeycloakConfigResolverConfig.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/KeycloakConfigResolverConfig.java new file mode 100644 index 0000000000..bca764a17d --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/KeycloakConfigResolverConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.swaggerkeycloak; + +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class KeycloakConfigResolverConfig { + + /* + * re-configure keycloak adapter for Spring Boot environment, + * i.e. to read config from application.yml + * (otherwise, we need a keycloak.json file) + */ + @Bean + public KeycloakConfigResolver configResolver() { + return new KeycloakSpringBootConfigResolver(); + } + + + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/OpenAPISecurityConfig.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/OpenAPISecurityConfig.java new file mode 100644 index 0000000000..d3ab26e1ee --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/OpenAPISecurityConfig.java @@ -0,0 +1,83 @@ +package com.baeldung.swaggerkeycloak; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import springfox.documentation.builders.OAuth2SchemeBuilder; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.service.SecurityScheme; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger.web.SecurityConfiguration; +import springfox.documentation.swagger.web.SecurityConfigurationBuilder; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Configuration +public class OpenAPISecurityConfig { + + @Value("${keycloak.auth-server-url}") + String authServerUrl; + @Value("${keycloak.realm}") + String realm; + @Value("${keycloak.resource}") + private String clientId; + @Value("${keycloak.credentials.secret}") + private String clientSecret; + + @Autowired + void addSecurity(Docket docket) { + docket + .securitySchemes(Collections.singletonList(authenticationScheme())) + .securityContexts(Collections.singletonList(securityContext())); + } + + private SecurityScheme authenticationScheme() { + return new OAuth2SchemeBuilder("implicit") + .name("my_oAuth_security_schema") + .authorizationUrl(authServerUrl + "/realms/" + realm) + .scopes(authorizationScopes()) + .build(); + } + + private List authorizationScopes() { + return Arrays.asList( + new AuthorizationScope("read_access", "read data"), + new AuthorizationScope("write_access", "modify data") + ); + } + + private SecurityContext securityContext() { + return SecurityContext. + builder(). + securityReferences(readAccessAuth()) + .operationSelector(operationContext -> HttpMethod.GET.equals(operationContext.httpMethod())) + .build(); + } + + private List readAccessAuth() { + AuthorizationScope[] authorizationScopes = new AuthorizationScope[] { authorizationScopes().get(0) }; + return Collections.singletonList( + new SecurityReference("my_oAuth_security_schema", authorizationScopes) + ); + } + + @Bean + public SecurityConfiguration security() { + return SecurityConfigurationBuilder.builder() + .clientId(clientId) + .clientSecret(clientSecret) + .realm(realm) + .appName(clientId) + .scopeSeparator(",") + .additionalQueryStringParams(null) + .useBasicAuthenticationWithAccessCodeGrant(false) + .build(); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/SwaggerUIConfig.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/SwaggerUIConfig.java new file mode 100644 index 0000000000..1207fe5b9e --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/SwaggerUIConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.swaggerkeycloak; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.oas.annotations.EnableOpenApi; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; + +@EnableOpenApi +@Configuration +class SwaggerUIConfig { + + @Bean + Docket api() { + return new Docket(DocumentationType.OAS_30) + .useDefaultResponseMessages(false) + .select() + .apis(basePackage(TodosApplication.class.getPackage().getName())) + .paths(PathSelectors.any()) + .build() + .apiInfo(apiInfo()); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder().title("Todos Management Service") + .description("A service providing todos.") + .version("1.0") + .build(); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/Todo.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/Todo.java new file mode 100644 index 0000000000..5423f9e342 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/Todo.java @@ -0,0 +1,44 @@ +package com.baeldung.swaggerkeycloak; + +import java.time.LocalDate; + +public class Todo { + + private Long id; + private String title; + private LocalDate dueDate; + + public Todo() { + } + + public Todo(Long id, String title, LocalDate dueDate) { + this.id = id; + this.title = title; + this.dueDate = dueDate; + } + + 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 LocalDate getDueDate() { + return dueDate; + } + + public void setDueDate(LocalDate dueDate) { + this.dueDate = dueDate; + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosApplication.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosApplication.java new file mode 100644 index 0000000000..20abbd8f10 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerkeycloak; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TodosApplication { + + public static void main(String[] args) { + SpringApplication.run(TodosApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosController.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosController.java new file mode 100644 index 0000000000..6b70072ce3 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/TodosController.java @@ -0,0 +1,40 @@ +package com.baeldung.swaggerkeycloak; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.PostConstruct; +import java.time.LocalDate; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/todos") +public class TodosController { + + private final Map todos = new HashMap<>(); + + @PostConstruct + public void initData() { + todos.put(1L, new Todo(1L, "Install Keycloak", LocalDate.now().plusDays(14))); + todos.put(2L, new Todo(2L, "Configure realm", LocalDate.now().plusDays(21))); + } + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Read all todos") + @ApiResponses({ + @ApiResponse(code = 200, message = "The todos were found and returned.") + }) + @PreAuthorize("hasAuthority('SCOPE_read_access')") + public Collection readAll() { + return todos.values(); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-16x16.png b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-16x16.png new file mode 100644 index 0000000000..8b194e617a Binary files /dev/null and b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-16x16.png differ diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-32x32.png b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-32x32.png new file mode 100644 index 0000000000..249737fe44 Binary files /dev/null and b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/favicon-32x32.png differ diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/oauth2-redirect.html b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/oauth2-redirect.html new file mode 100644 index 0000000000..64b171f7de --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/oauth2-redirect.html @@ -0,0 +1,75 @@ + + + + Swagger UI: OAuth2 Redirect + + + + + diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/swagger-ui.css b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/swagger-ui.css new file mode 100644 index 0000000000..e43a572a13 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/META-INF/resources/webjars/springfox-swagger-ui/swagger-ui.css @@ -0,0 +1,4 @@ +.swagger-ui{color:#3b4151; + /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */font-family:sans-serif}.swagger-ui html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.15}.swagger-ui body{margin:0}.swagger-ui article,.swagger-ui aside,.swagger-ui footer,.swagger-ui header,.swagger-ui nav,.swagger-ui section{display:block}.swagger-ui h1{font-size:2em;margin:.67em 0}.swagger-ui figcaption,.swagger-ui figure,.swagger-ui main{display:block}.swagger-ui figure{margin:1em 40px}.swagger-ui hr{box-sizing:content-box;height:0;overflow:visible}.swagger-ui pre{font-family:monospace,monospace;font-size:1em}.swagger-ui a{-webkit-text-decoration-skip:objects;background-color:transparent}.swagger-ui abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.swagger-ui b,.swagger-ui strong{font-weight:inherit;font-weight:bolder}.swagger-ui code,.swagger-ui kbd,.swagger-ui samp{font-family:monospace,monospace;font-size:1em}.swagger-ui dfn{font-style:italic}.swagger-ui mark{background-color:#ff0;color:#000}.swagger-ui small{font-size:80%}.swagger-ui sub,.swagger-ui sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.swagger-ui sub{bottom:-.25em}.swagger-ui sup{top:-.5em}.swagger-ui audio,.swagger-ui video{display:inline-block}.swagger-ui audio:not([controls]){display:none;height:0}.swagger-ui img{border-style:none}.swagger-ui svg:not(:root){overflow:hidden}.swagger-ui button,.swagger-ui input,.swagger-ui optgroup,.swagger-ui select,.swagger-ui textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}.swagger-ui button,.swagger-ui input{overflow:visible}.swagger-ui button,.swagger-ui select{text-transform:none}.swagger-ui [type=reset],.swagger-ui [type=submit],.swagger-ui button,.swagger-ui html [type=button]{-webkit-appearance:button}.swagger-ui [type=button]::-moz-focus-inner,.swagger-ui [type=reset]::-moz-focus-inner,.swagger-ui [type=submit]::-moz-focus-inner,.swagger-ui button::-moz-focus-inner{border-style:none;padding:0}.swagger-ui [type=button]:-moz-focusring,.swagger-ui [type=reset]:-moz-focusring,.swagger-ui [type=submit]:-moz-focusring,.swagger-ui button:-moz-focusring{outline:1px dotted ButtonText}.swagger-ui fieldset{padding:.35em .75em .625em}.swagger-ui legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}.swagger-ui progress{display:inline-block;vertical-align:baseline}.swagger-ui textarea{overflow:auto}.swagger-ui [type=checkbox],.swagger-ui [type=radio]{box-sizing:border-box;padding:0}.swagger-ui [type=number]::-webkit-inner-spin-button,.swagger-ui [type=number]::-webkit-outer-spin-button{height:auto}.swagger-ui [type=search]{-webkit-appearance:textfield;outline-offset:-2px}.swagger-ui [type=search]::-webkit-search-cancel-button,.swagger-ui [type=search]::-webkit-search-decoration{-webkit-appearance:none}.swagger-ui ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.swagger-ui details,.swagger-ui menu{display:block}.swagger-ui summary{display:list-item}.swagger-ui canvas{display:inline-block}.swagger-ui [hidden],.swagger-ui template{display:none}.swagger-ui .debug *{outline:1px solid gold}.swagger-ui .debug-white *{outline:1px solid #fff}.swagger-ui .debug-black *{outline:1px solid #000}.swagger-ui .debug-grid{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) repeat 0 0}.swagger-ui .debug-grid-16{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC) repeat 0 0}.swagger-ui .debug-grid-8-solid{background:#fff url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z) repeat 0 0}.swagger-ui .debug-grid-16-solid{background:#fff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) repeat 0 0}.swagger-ui .border-box,.swagger-ui a,.swagger-ui article,.swagger-ui body,.swagger-ui code,.swagger-ui dd,.swagger-ui div,.swagger-ui dl,.swagger-ui dt,.swagger-ui fieldset,.swagger-ui footer,.swagger-ui form,.swagger-ui h1,.swagger-ui h2,.swagger-ui h3,.swagger-ui h4,.swagger-ui h5,.swagger-ui h6,.swagger-ui header,.swagger-ui html,.swagger-ui input[type=email],.swagger-ui input[type=number],.swagger-ui input[type=password],.swagger-ui input[type=tel],.swagger-ui input[type=text],.swagger-ui input[type=url],.swagger-ui legend,.swagger-ui li,.swagger-ui main,.swagger-ui ol,.swagger-ui p,.swagger-ui pre,.swagger-ui section,.swagger-ui table,.swagger-ui td,.swagger-ui textarea,.swagger-ui th,.swagger-ui tr,.swagger-ui ul{box-sizing:border-box}.swagger-ui .aspect-ratio{height:0;position:relative}.swagger-ui .aspect-ratio--16x9{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1{padding-bottom:100%}.swagger-ui .aspect-ratio--object{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}@media screen and (min-width:30em){.swagger-ui .aspect-ratio-ns{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-ns{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-ns{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-ns{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-ns{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-ns{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-ns{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-ns{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-ns{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-ns{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-ns{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-ns{padding-bottom:100%}.swagger-ui .aspect-ratio--object-ns{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .aspect-ratio-m{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-m{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-m{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-m{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-m{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-m{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-m{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-m{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-m{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-m{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-m{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-m{padding-bottom:100%}.swagger-ui .aspect-ratio--object-m{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}@media screen and (min-width:60em){.swagger-ui .aspect-ratio-l{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-l{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-l{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-l{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-l{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-l{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-l{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-l{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-l{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-l{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-l{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-l{padding-bottom:100%}.swagger-ui .aspect-ratio--object-l{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}.swagger-ui img{max-width:100%}.swagger-ui .cover{background-size:cover!important}.swagger-ui .contain{background-size:contain!important}@media screen and (min-width:30em){.swagger-ui .cover-ns{background-size:cover!important}.swagger-ui .contain-ns{background-size:contain!important}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .cover-m{background-size:cover!important}.swagger-ui .contain-m{background-size:contain!important}}@media screen and (min-width:60em){.swagger-ui .cover-l{background-size:cover!important}.swagger-ui .contain-l{background-size:contain!important}}.swagger-ui .bg-center{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left{background-position:0;background-repeat:no-repeat}@media screen and (min-width:30em){.swagger-ui .bg-center-ns{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-ns{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-ns{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-ns{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-ns{background-position:0;background-repeat:no-repeat}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .bg-center-m{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-m{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-m{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-m{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-m{background-position:0;background-repeat:no-repeat}}@media screen and (min-width:60em){.swagger-ui .bg-center-l{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-l{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-l{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-l{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-l{background-position:0;background-repeat:no-repeat}}.swagger-ui .outline{outline:1px solid}.swagger-ui .outline-transparent{outline:1px solid transparent}.swagger-ui .outline-0{outline:0}@media screen and (min-width:30em){.swagger-ui .outline-ns{outline:1px solid}.swagger-ui .outline-transparent-ns{outline:1px solid transparent}.swagger-ui .outline-0-ns{outline:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .outline-m{outline:1px solid}.swagger-ui .outline-transparent-m{outline:1px solid transparent}.swagger-ui .outline-0-m{outline:0}}@media screen and (min-width:60em){.swagger-ui .outline-l{outline:1px solid}.swagger-ui .outline-transparent-l{outline:1px solid transparent}.swagger-ui .outline-0-l{outline:0}}.swagger-ui .ba{border-style:solid;border-width:1px}.swagger-ui .bt{border-top-style:solid;border-top-width:1px}.swagger-ui .br{border-right-style:solid;border-right-width:1px}.swagger-ui .bb{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl{border-left-style:solid;border-left-width:1px}.swagger-ui .bn{border-style:none;border-width:0}@media screen and (min-width:30em){.swagger-ui .ba-ns{border-style:solid;border-width:1px}.swagger-ui .bt-ns{border-top-style:solid;border-top-width:1px}.swagger-ui .br-ns{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-ns{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-ns{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-ns{border-style:none;border-width:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ba-m{border-style:solid;border-width:1px}.swagger-ui .bt-m{border-top-style:solid;border-top-width:1px}.swagger-ui .br-m{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-m{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-m{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-m{border-style:none;border-width:0}}@media screen and (min-width:60em){.swagger-ui .ba-l{border-style:solid;border-width:1px}.swagger-ui .bt-l{border-top-style:solid;border-top-width:1px}.swagger-ui .br-l{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-l{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-l{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-l{border-style:none;border-width:0}}.swagger-ui .b--black{border-color:#000}.swagger-ui .b--near-black{border-color:#111}.swagger-ui .b--dark-gray{border-color:#333}.swagger-ui .b--mid-gray{border-color:#555}.swagger-ui .b--gray{border-color:#777}.swagger-ui .b--silver{border-color:#999}.swagger-ui .b--light-silver{border-color:#aaa}.swagger-ui .b--moon-gray{border-color:#ccc}.swagger-ui .b--light-gray{border-color:#eee}.swagger-ui .b--near-white{border-color:#f4f4f4}.swagger-ui .b--white{border-color:#fff}.swagger-ui .b--white-90{border-color:hsla(0,0%,100%,.9)}.swagger-ui .b--white-80{border-color:hsla(0,0%,100%,.8)}.swagger-ui .b--white-70{border-color:hsla(0,0%,100%,.7)}.swagger-ui .b--white-60{border-color:hsla(0,0%,100%,.6)}.swagger-ui .b--white-50{border-color:hsla(0,0%,100%,.5)}.swagger-ui .b--white-40{border-color:hsla(0,0%,100%,.4)}.swagger-ui .b--white-30{border-color:hsla(0,0%,100%,.3)}.swagger-ui .b--white-20{border-color:hsla(0,0%,100%,.2)}.swagger-ui .b--white-10{border-color:hsla(0,0%,100%,.1)}.swagger-ui .b--white-05{border-color:hsla(0,0%,100%,.05)}.swagger-ui .b--white-025{border-color:hsla(0,0%,100%,.025)}.swagger-ui .b--white-0125{border-color:hsla(0,0%,100%,.013)}.swagger-ui .b--black-90{border-color:rgba(0,0,0,.9)}.swagger-ui .b--black-80{border-color:rgba(0,0,0,.8)}.swagger-ui .b--black-70{border-color:rgba(0,0,0,.7)}.swagger-ui .b--black-60{border-color:rgba(0,0,0,.6)}.swagger-ui .b--black-50{border-color:rgba(0,0,0,.5)}.swagger-ui .b--black-40{border-color:rgba(0,0,0,.4)}.swagger-ui .b--black-30{border-color:rgba(0,0,0,.3)}.swagger-ui .b--black-20{border-color:rgba(0,0,0,.2)}.swagger-ui .b--black-10{border-color:rgba(0,0,0,.1)}.swagger-ui .b--black-05{border-color:rgba(0,0,0,.05)}.swagger-ui .b--black-025{border-color:rgba(0,0,0,.025)}.swagger-ui .b--black-0125{border-color:rgba(0,0,0,.013)}.swagger-ui .b--dark-red{border-color:#e7040f}.swagger-ui .b--red{border-color:#ff4136}.swagger-ui .b--light-red{border-color:#ff725c}.swagger-ui .b--orange{border-color:#ff6300}.swagger-ui .b--gold{border-color:#ffb700}.swagger-ui .b--yellow{border-color:gold}.swagger-ui .b--light-yellow{border-color:#fbf1a9}.swagger-ui .b--purple{border-color:#5e2ca5}.swagger-ui .b--light-purple{border-color:#a463f2}.swagger-ui .b--dark-pink{border-color:#d5008f}.swagger-ui .b--hot-pink{border-color:#ff41b4}.swagger-ui .b--pink{border-color:#ff80cc}.swagger-ui .b--light-pink{border-color:#ffa3d7}.swagger-ui .b--dark-green{border-color:#137752}.swagger-ui .b--green{border-color:#19a974}.swagger-ui .b--light-green{border-color:#9eebcf}.swagger-ui .b--navy{border-color:#001b44}.swagger-ui .b--dark-blue{border-color:#00449e}.swagger-ui .b--blue{border-color:#357edd}.swagger-ui .b--light-blue{border-color:#96ccff}.swagger-ui .b--lightest-blue{border-color:#cdecff}.swagger-ui .b--washed-blue{border-color:#f6fffe}.swagger-ui .b--washed-green{border-color:#e8fdf5}.swagger-ui .b--washed-yellow{border-color:#fffceb}.swagger-ui .b--washed-red{border-color:#ffdfdf}.swagger-ui .b--transparent{border-color:transparent}.swagger-ui .b--inherit{border-color:inherit}.swagger-ui .br0{border-radius:0}.swagger-ui .br1{border-radius:.125rem}.swagger-ui .br2{border-radius:.25rem}.swagger-ui .br3{border-radius:.5rem}.swagger-ui .br4{border-radius:1rem}.swagger-ui .br-100{border-radius:100%}.swagger-ui .br-pill{border-radius:9999px}.swagger-ui .br--bottom{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left{border-bottom-right-radius:0;border-top-right-radius:0}@media screen and (min-width:30em){.swagger-ui .br0-ns{border-radius:0}.swagger-ui .br1-ns{border-radius:.125rem}.swagger-ui .br2-ns{border-radius:.25rem}.swagger-ui .br3-ns{border-radius:.5rem}.swagger-ui .br4-ns{border-radius:1rem}.swagger-ui .br-100-ns{border-radius:100%}.swagger-ui .br-pill-ns{border-radius:9999px}.swagger-ui .br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-ns{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-ns{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-ns{border-bottom-right-radius:0;border-top-right-radius:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .br0-m{border-radius:0}.swagger-ui .br1-m{border-radius:.125rem}.swagger-ui .br2-m{border-radius:.25rem}.swagger-ui .br3-m{border-radius:.5rem}.swagger-ui .br4-m{border-radius:1rem}.swagger-ui .br-100-m{border-radius:100%}.swagger-ui .br-pill-m{border-radius:9999px}.swagger-ui .br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-m{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-m{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-m{border-bottom-right-radius:0;border-top-right-radius:0}}@media screen and (min-width:60em){.swagger-ui .br0-l{border-radius:0}.swagger-ui .br1-l{border-radius:.125rem}.swagger-ui .br2-l{border-radius:.25rem}.swagger-ui .br3-l{border-radius:.5rem}.swagger-ui .br4-l{border-radius:1rem}.swagger-ui .br-100-l{border-radius:100%}.swagger-ui .br-pill-l{border-radius:9999px}.swagger-ui .br--bottom-l{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-l{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-l{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-l{border-bottom-right-radius:0;border-top-right-radius:0}}.swagger-ui .b--dotted{border-style:dotted}.swagger-ui .b--dashed{border-style:dashed}.swagger-ui .b--solid{border-style:solid}.swagger-ui .b--none{border-style:none}@media screen and (min-width:30em){.swagger-ui .b--dotted-ns{border-style:dotted}.swagger-ui .b--dashed-ns{border-style:dashed}.swagger-ui .b--solid-ns{border-style:solid}.swagger-ui .b--none-ns{border-style:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .b--dotted-m{border-style:dotted}.swagger-ui .b--dashed-m{border-style:dashed}.swagger-ui .b--solid-m{border-style:solid}.swagger-ui .b--none-m{border-style:none}}@media screen and (min-width:60em){.swagger-ui .b--dotted-l{border-style:dotted}.swagger-ui .b--dashed-l{border-style:dashed}.swagger-ui .b--solid-l{border-style:solid}.swagger-ui .b--none-l{border-style:none}}.swagger-ui .bw0{border-width:0}.swagger-ui .bw1{border-width:.125rem}.swagger-ui .bw2{border-width:.25rem}.swagger-ui .bw3{border-width:.5rem}.swagger-ui .bw4{border-width:1rem}.swagger-ui .bw5{border-width:2rem}.swagger-ui .bt-0{border-top-width:0}.swagger-ui .br-0{border-right-width:0}.swagger-ui .bb-0{border-bottom-width:0}.swagger-ui .bl-0{border-left-width:0}@media screen and (min-width:30em){.swagger-ui .bw0-ns{border-width:0}.swagger-ui .bw1-ns{border-width:.125rem}.swagger-ui .bw2-ns{border-width:.25rem}.swagger-ui .bw3-ns{border-width:.5rem}.swagger-ui .bw4-ns{border-width:1rem}.swagger-ui .bw5-ns{border-width:2rem}.swagger-ui .bt-0-ns{border-top-width:0}.swagger-ui .br-0-ns{border-right-width:0}.swagger-ui .bb-0-ns{border-bottom-width:0}.swagger-ui .bl-0-ns{border-left-width:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .bw0-m{border-width:0}.swagger-ui .bw1-m{border-width:.125rem}.swagger-ui .bw2-m{border-width:.25rem}.swagger-ui .bw3-m{border-width:.5rem}.swagger-ui .bw4-m{border-width:1rem}.swagger-ui .bw5-m{border-width:2rem}.swagger-ui .bt-0-m{border-top-width:0}.swagger-ui .br-0-m{border-right-width:0}.swagger-ui .bb-0-m{border-bottom-width:0}.swagger-ui .bl-0-m{border-left-width:0}}@media screen and (min-width:60em){.swagger-ui .bw0-l{border-width:0}.swagger-ui .bw1-l{border-width:.125rem}.swagger-ui .bw2-l{border-width:.25rem}.swagger-ui .bw3-l{border-width:.5rem}.swagger-ui .bw4-l{border-width:1rem}.swagger-ui .bw5-l{border-width:2rem}.swagger-ui .bt-0-l{border-top-width:0}.swagger-ui .br-0-l{border-right-width:0}.swagger-ui .bb-0-l{border-bottom-width:0}.swagger-ui .bl-0-l{border-left-width:0}}.swagger-ui .shadow-1{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}@media screen and (min-width:30em){.swagger-ui .shadow-1-ns{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-ns{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-ns{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-ns{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-ns{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .shadow-1-m{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-m{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-m{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-m{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-m{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:60em){.swagger-ui .shadow-1-l{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-l{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-l{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-l{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-l{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}.swagger-ui .pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}.swagger-ui .top-0{top:0}.swagger-ui .right-0{right:0}.swagger-ui .bottom-0{bottom:0}.swagger-ui .left-0{left:0}.swagger-ui .top-1{top:1rem}.swagger-ui .right-1{right:1rem}.swagger-ui .bottom-1{bottom:1rem}.swagger-ui .left-1{left:1rem}.swagger-ui .top-2{top:2rem}.swagger-ui .right-2{right:2rem}.swagger-ui .bottom-2{bottom:2rem}.swagger-ui .left-2{left:2rem}.swagger-ui .top--1{top:-1rem}.swagger-ui .right--1{right:-1rem}.swagger-ui .bottom--1{bottom:-1rem}.swagger-ui .left--1{left:-1rem}.swagger-ui .top--2{top:-2rem}.swagger-ui .right--2{right:-2rem}.swagger-ui .bottom--2{bottom:-2rem}.swagger-ui .left--2{left:-2rem}.swagger-ui .absolute--fill{bottom:0;left:0;right:0;top:0}@media screen and (min-width:30em){.swagger-ui .top-0-ns{top:0}.swagger-ui .left-0-ns{left:0}.swagger-ui .right-0-ns{right:0}.swagger-ui .bottom-0-ns{bottom:0}.swagger-ui .top-1-ns{top:1rem}.swagger-ui .left-1-ns{left:1rem}.swagger-ui .right-1-ns{right:1rem}.swagger-ui .bottom-1-ns{bottom:1rem}.swagger-ui .top-2-ns{top:2rem}.swagger-ui .left-2-ns{left:2rem}.swagger-ui .right-2-ns{right:2rem}.swagger-ui .bottom-2-ns{bottom:2rem}.swagger-ui .top--1-ns{top:-1rem}.swagger-ui .right--1-ns{right:-1rem}.swagger-ui .bottom--1-ns{bottom:-1rem}.swagger-ui .left--1-ns{left:-1rem}.swagger-ui .top--2-ns{top:-2rem}.swagger-ui .right--2-ns{right:-2rem}.swagger-ui .bottom--2-ns{bottom:-2rem}.swagger-ui .left--2-ns{left:-2rem}.swagger-ui .absolute--fill-ns{bottom:0;left:0;right:0;top:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .top-0-m{top:0}.swagger-ui .left-0-m{left:0}.swagger-ui .right-0-m{right:0}.swagger-ui .bottom-0-m{bottom:0}.swagger-ui .top-1-m{top:1rem}.swagger-ui .left-1-m{left:1rem}.swagger-ui .right-1-m{right:1rem}.swagger-ui .bottom-1-m{bottom:1rem}.swagger-ui .top-2-m{top:2rem}.swagger-ui .left-2-m{left:2rem}.swagger-ui .right-2-m{right:2rem}.swagger-ui .bottom-2-m{bottom:2rem}.swagger-ui .top--1-m{top:-1rem}.swagger-ui .right--1-m{right:-1rem}.swagger-ui .bottom--1-m{bottom:-1rem}.swagger-ui .left--1-m{left:-1rem}.swagger-ui .top--2-m{top:-2rem}.swagger-ui .right--2-m{right:-2rem}.swagger-ui .bottom--2-m{bottom:-2rem}.swagger-ui .left--2-m{left:-2rem}.swagger-ui .absolute--fill-m{bottom:0;left:0;right:0;top:0}}@media screen and (min-width:60em){.swagger-ui .top-0-l{top:0}.swagger-ui .left-0-l{left:0}.swagger-ui .right-0-l{right:0}.swagger-ui .bottom-0-l{bottom:0}.swagger-ui .top-1-l{top:1rem}.swagger-ui .left-1-l{left:1rem}.swagger-ui .right-1-l{right:1rem}.swagger-ui .bottom-1-l{bottom:1rem}.swagger-ui .top-2-l{top:2rem}.swagger-ui .left-2-l{left:2rem}.swagger-ui .right-2-l{right:2rem}.swagger-ui .bottom-2-l{bottom:2rem}.swagger-ui .top--1-l{top:-1rem}.swagger-ui .right--1-l{right:-1rem}.swagger-ui .bottom--1-l{bottom:-1rem}.swagger-ui .left--1-l{left:-1rem}.swagger-ui .top--2-l{top:-2rem}.swagger-ui .right--2-l{right:-2rem}.swagger-ui .bottom--2-l{bottom:-2rem}.swagger-ui .left--2-l{left:-2rem}.swagger-ui .absolute--fill-l{bottom:0;left:0;right:0;top:0}}.swagger-ui .cf:after,.swagger-ui .cf:before{content:" ";display:table}.swagger-ui .cf:after{clear:both}.swagger-ui .cf{*zoom:1}.swagger-ui .cl{clear:left}.swagger-ui .cr{clear:right}.swagger-ui .cb{clear:both}.swagger-ui .cn{clear:none}@media screen and (min-width:30em){.swagger-ui .cl-ns{clear:left}.swagger-ui .cr-ns{clear:right}.swagger-ui .cb-ns{clear:both}.swagger-ui .cn-ns{clear:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .cl-m{clear:left}.swagger-ui .cr-m{clear:right}.swagger-ui .cb-m{clear:both}.swagger-ui .cn-m{clear:none}}@media screen and (min-width:60em){.swagger-ui .cl-l{clear:left}.swagger-ui .cr-l{clear:right}.swagger-ui .cb-l{clear:both}.swagger-ui .cn-l{clear:none}}.swagger-ui .flex{display:flex}.swagger-ui .inline-flex{display:inline-flex}.swagger-ui .flex-auto{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none{flex:none}.swagger-ui .flex-column{flex-direction:column}.swagger-ui .flex-row{flex-direction:row}.swagger-ui .flex-wrap{flex-wrap:wrap}.swagger-ui .flex-nowrap{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse{flex-direction:column-reverse}.swagger-ui .flex-row-reverse{flex-direction:row-reverse}.swagger-ui .items-start{align-items:flex-start}.swagger-ui .items-end{align-items:flex-end}.swagger-ui .items-center{align-items:center}.swagger-ui .items-baseline{align-items:baseline}.swagger-ui .items-stretch{align-items:stretch}.swagger-ui .self-start{align-self:flex-start}.swagger-ui .self-end{align-self:flex-end}.swagger-ui .self-center{align-self:center}.swagger-ui .self-baseline{align-self:baseline}.swagger-ui .self-stretch{align-self:stretch}.swagger-ui .justify-start{justify-content:flex-start}.swagger-ui .justify-end{justify-content:flex-end}.swagger-ui .justify-center{justify-content:center}.swagger-ui .justify-between{justify-content:space-between}.swagger-ui .justify-around{justify-content:space-around}.swagger-ui .content-start{align-content:flex-start}.swagger-ui .content-end{align-content:flex-end}.swagger-ui .content-center{align-content:center}.swagger-ui .content-between{align-content:space-between}.swagger-ui .content-around{align-content:space-around}.swagger-ui .content-stretch{align-content:stretch}.swagger-ui .order-0{order:0}.swagger-ui .order-1{order:1}.swagger-ui .order-2{order:2}.swagger-ui .order-3{order:3}.swagger-ui .order-4{order:4}.swagger-ui .order-5{order:5}.swagger-ui .order-6{order:6}.swagger-ui .order-7{order:7}.swagger-ui .order-8{order:8}.swagger-ui .order-last{order:99999}.swagger-ui .flex-grow-0{flex-grow:0}.swagger-ui .flex-grow-1{flex-grow:1}.swagger-ui .flex-shrink-0{flex-shrink:0}.swagger-ui .flex-shrink-1{flex-shrink:1}@media screen and (min-width:30em){.swagger-ui .flex-ns{display:flex}.swagger-ui .inline-flex-ns{display:inline-flex}.swagger-ui .flex-auto-ns{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-ns{flex:none}.swagger-ui .flex-column-ns{flex-direction:column}.swagger-ui .flex-row-ns{flex-direction:row}.swagger-ui .flex-wrap-ns{flex-wrap:wrap}.swagger-ui .flex-nowrap-ns{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-ns{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-ns{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-ns{flex-direction:row-reverse}.swagger-ui .items-start-ns{align-items:flex-start}.swagger-ui .items-end-ns{align-items:flex-end}.swagger-ui .items-center-ns{align-items:center}.swagger-ui .items-baseline-ns{align-items:baseline}.swagger-ui .items-stretch-ns{align-items:stretch}.swagger-ui .self-start-ns{align-self:flex-start}.swagger-ui .self-end-ns{align-self:flex-end}.swagger-ui .self-center-ns{align-self:center}.swagger-ui .self-baseline-ns{align-self:baseline}.swagger-ui .self-stretch-ns{align-self:stretch}.swagger-ui .justify-start-ns{justify-content:flex-start}.swagger-ui .justify-end-ns{justify-content:flex-end}.swagger-ui .justify-center-ns{justify-content:center}.swagger-ui .justify-between-ns{justify-content:space-between}.swagger-ui .justify-around-ns{justify-content:space-around}.swagger-ui .content-start-ns{align-content:flex-start}.swagger-ui .content-end-ns{align-content:flex-end}.swagger-ui .content-center-ns{align-content:center}.swagger-ui .content-between-ns{align-content:space-between}.swagger-ui .content-around-ns{align-content:space-around}.swagger-ui .content-stretch-ns{align-content:stretch}.swagger-ui .order-0-ns{order:0}.swagger-ui .order-1-ns{order:1}.swagger-ui .order-2-ns{order:2}.swagger-ui .order-3-ns{order:3}.swagger-ui .order-4-ns{order:4}.swagger-ui .order-5-ns{order:5}.swagger-ui .order-6-ns{order:6}.swagger-ui .order-7-ns{order:7}.swagger-ui .order-8-ns{order:8}.swagger-ui .order-last-ns{order:99999}.swagger-ui .flex-grow-0-ns{flex-grow:0}.swagger-ui .flex-grow-1-ns{flex-grow:1}.swagger-ui .flex-shrink-0-ns{flex-shrink:0}.swagger-ui .flex-shrink-1-ns{flex-shrink:1}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .flex-m{display:flex}.swagger-ui .inline-flex-m{display:inline-flex}.swagger-ui .flex-auto-m{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-m{flex:none}.swagger-ui .flex-column-m{flex-direction:column}.swagger-ui .flex-row-m{flex-direction:row}.swagger-ui .flex-wrap-m{flex-wrap:wrap}.swagger-ui .flex-nowrap-m{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-m{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-m{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-m{flex-direction:row-reverse}.swagger-ui .items-start-m{align-items:flex-start}.swagger-ui .items-end-m{align-items:flex-end}.swagger-ui .items-center-m{align-items:center}.swagger-ui .items-baseline-m{align-items:baseline}.swagger-ui .items-stretch-m{align-items:stretch}.swagger-ui .self-start-m{align-self:flex-start}.swagger-ui .self-end-m{align-self:flex-end}.swagger-ui .self-center-m{align-self:center}.swagger-ui .self-baseline-m{align-self:baseline}.swagger-ui .self-stretch-m{align-self:stretch}.swagger-ui .justify-start-m{justify-content:flex-start}.swagger-ui .justify-end-m{justify-content:flex-end}.swagger-ui .justify-center-m{justify-content:center}.swagger-ui .justify-between-m{justify-content:space-between}.swagger-ui .justify-around-m{justify-content:space-around}.swagger-ui .content-start-m{align-content:flex-start}.swagger-ui .content-end-m{align-content:flex-end}.swagger-ui .content-center-m{align-content:center}.swagger-ui .content-between-m{align-content:space-between}.swagger-ui .content-around-m{align-content:space-around}.swagger-ui .content-stretch-m{align-content:stretch}.swagger-ui .order-0-m{order:0}.swagger-ui .order-1-m{order:1}.swagger-ui .order-2-m{order:2}.swagger-ui .order-3-m{order:3}.swagger-ui .order-4-m{order:4}.swagger-ui .order-5-m{order:5}.swagger-ui .order-6-m{order:6}.swagger-ui .order-7-m{order:7}.swagger-ui .order-8-m{order:8}.swagger-ui .order-last-m{order:99999}.swagger-ui .flex-grow-0-m{flex-grow:0}.swagger-ui .flex-grow-1-m{flex-grow:1}.swagger-ui .flex-shrink-0-m{flex-shrink:0}.swagger-ui .flex-shrink-1-m{flex-shrink:1}}@media screen and (min-width:60em){.swagger-ui .flex-l{display:flex}.swagger-ui .inline-flex-l{display:inline-flex}.swagger-ui .flex-auto-l{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-l{flex:none}.swagger-ui .flex-column-l{flex-direction:column}.swagger-ui .flex-row-l{flex-direction:row}.swagger-ui .flex-wrap-l{flex-wrap:wrap}.swagger-ui .flex-nowrap-l{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-l{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-l{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-l{flex-direction:row-reverse}.swagger-ui .items-start-l{align-items:flex-start}.swagger-ui .items-end-l{align-items:flex-end}.swagger-ui .items-center-l{align-items:center}.swagger-ui .items-baseline-l{align-items:baseline}.swagger-ui .items-stretch-l{align-items:stretch}.swagger-ui .self-start-l{align-self:flex-start}.swagger-ui .self-end-l{align-self:flex-end}.swagger-ui .self-center-l{align-self:center}.swagger-ui .self-baseline-l{align-self:baseline}.swagger-ui .self-stretch-l{align-self:stretch}.swagger-ui .justify-start-l{justify-content:flex-start}.swagger-ui .justify-end-l{justify-content:flex-end}.swagger-ui .justify-center-l{justify-content:center}.swagger-ui .justify-between-l{justify-content:space-between}.swagger-ui .justify-around-l{justify-content:space-around}.swagger-ui .content-start-l{align-content:flex-start}.swagger-ui .content-end-l{align-content:flex-end}.swagger-ui .content-center-l{align-content:center}.swagger-ui .content-between-l{align-content:space-between}.swagger-ui .content-around-l{align-content:space-around}.swagger-ui .content-stretch-l{align-content:stretch}.swagger-ui .order-0-l{order:0}.swagger-ui .order-1-l{order:1}.swagger-ui .order-2-l{order:2}.swagger-ui .order-3-l{order:3}.swagger-ui .order-4-l{order:4}.swagger-ui .order-5-l{order:5}.swagger-ui .order-6-l{order:6}.swagger-ui .order-7-l{order:7}.swagger-ui .order-8-l{order:8}.swagger-ui .order-last-l{order:99999}.swagger-ui .flex-grow-0-l{flex-grow:0}.swagger-ui .flex-grow-1-l{flex-grow:1}.swagger-ui .flex-shrink-0-l{flex-shrink:0}.swagger-ui .flex-shrink-1-l{flex-shrink:1}}.swagger-ui .dn{display:none}.swagger-ui .di{display:inline}.swagger-ui .db{display:block}.swagger-ui .dib{display:inline-block}.swagger-ui .dit{display:inline-table}.swagger-ui .dt{display:table}.swagger-ui .dtc{display:table-cell}.swagger-ui .dt-row{display:table-row}.swagger-ui .dt-row-group{display:table-row-group}.swagger-ui .dt-column{display:table-column}.swagger-ui .dt-column-group{display:table-column-group}.swagger-ui .dt--fixed{table-layout:fixed;width:100%}@media screen and (min-width:30em){.swagger-ui .dn-ns{display:none}.swagger-ui .di-ns{display:inline}.swagger-ui .db-ns{display:block}.swagger-ui .dib-ns{display:inline-block}.swagger-ui .dit-ns{display:inline-table}.swagger-ui .dt-ns{display:table}.swagger-ui .dtc-ns{display:table-cell}.swagger-ui .dt-row-ns{display:table-row}.swagger-ui .dt-row-group-ns{display:table-row-group}.swagger-ui .dt-column-ns{display:table-column}.swagger-ui .dt-column-group-ns{display:table-column-group}.swagger-ui .dt--fixed-ns{table-layout:fixed;width:100%}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .dn-m{display:none}.swagger-ui .di-m{display:inline}.swagger-ui .db-m{display:block}.swagger-ui .dib-m{display:inline-block}.swagger-ui .dit-m{display:inline-table}.swagger-ui .dt-m{display:table}.swagger-ui .dtc-m{display:table-cell}.swagger-ui .dt-row-m{display:table-row}.swagger-ui .dt-row-group-m{display:table-row-group}.swagger-ui .dt-column-m{display:table-column}.swagger-ui .dt-column-group-m{display:table-column-group}.swagger-ui .dt--fixed-m{table-layout:fixed;width:100%}}@media screen and (min-width:60em){.swagger-ui .dn-l{display:none}.swagger-ui .di-l{display:inline}.swagger-ui .db-l{display:block}.swagger-ui .dib-l{display:inline-block}.swagger-ui .dit-l{display:inline-table}.swagger-ui .dt-l{display:table}.swagger-ui .dtc-l{display:table-cell}.swagger-ui .dt-row-l{display:table-row}.swagger-ui .dt-row-group-l{display:table-row-group}.swagger-ui .dt-column-l{display:table-column}.swagger-ui .dt-column-group-l{display:table-column-group}.swagger-ui .dt--fixed-l{table-layout:fixed;width:100%}}.swagger-ui .fl{_display:inline;float:left}.swagger-ui .fr{_display:inline;float:right}.swagger-ui .fn{float:none}@media screen and (min-width:30em){.swagger-ui .fl-ns{_display:inline;float:left}.swagger-ui .fr-ns{_display:inline;float:right}.swagger-ui .fn-ns{float:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .fl-m{_display:inline;float:left}.swagger-ui .fr-m{_display:inline;float:right}.swagger-ui .fn-m{float:none}}@media screen and (min-width:60em){.swagger-ui .fl-l{_display:inline;float:left}.swagger-ui .fr-l{_display:inline;float:right}.swagger-ui .fn-l{float:none}}.swagger-ui .sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica,helvetica neue,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.swagger-ui .serif{font-family:georgia,serif}.swagger-ui .system-sans-serif{font-family:sans-serif}.swagger-ui .system-serif{font-family:serif}.swagger-ui .code,.swagger-ui code{font-family:Consolas,monaco,monospace}.swagger-ui .courier{font-family:Courier Next,courier,monospace}.swagger-ui .helvetica{font-family:helvetica neue,helvetica,sans-serif}.swagger-ui .avenir{font-family:avenir next,avenir,sans-serif}.swagger-ui .athelas{font-family:athelas,georgia,serif}.swagger-ui .georgia{font-family:georgia,serif}.swagger-ui .times{font-family:times,serif}.swagger-ui .bodoni{font-family:Bodoni MT,serif}.swagger-ui .calisto{font-family:Calisto MT,serif}.swagger-ui .garamond{font-family:garamond,serif}.swagger-ui .baskerville{font-family:baskerville,serif}.swagger-ui .i{font-style:italic}.swagger-ui .fs-normal{font-style:normal}@media screen and (min-width:30em){.swagger-ui .i-ns{font-style:italic}.swagger-ui .fs-normal-ns{font-style:normal}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .i-m{font-style:italic}.swagger-ui .fs-normal-m{font-style:normal}}@media screen and (min-width:60em){.swagger-ui .i-l{font-style:italic}.swagger-ui .fs-normal-l{font-style:normal}}.swagger-ui .normal{font-weight:400}.swagger-ui .b{font-weight:700}.swagger-ui .fw1{font-weight:100}.swagger-ui .fw2{font-weight:200}.swagger-ui .fw3{font-weight:300}.swagger-ui .fw4{font-weight:400}.swagger-ui .fw5{font-weight:500}.swagger-ui .fw6{font-weight:600}.swagger-ui .fw7{font-weight:700}.swagger-ui .fw8{font-weight:800}.swagger-ui .fw9{font-weight:900}@media screen and (min-width:30em){.swagger-ui .normal-ns{font-weight:400}.swagger-ui .b-ns{font-weight:700}.swagger-ui .fw1-ns{font-weight:100}.swagger-ui .fw2-ns{font-weight:200}.swagger-ui .fw3-ns{font-weight:300}.swagger-ui .fw4-ns{font-weight:400}.swagger-ui .fw5-ns{font-weight:500}.swagger-ui .fw6-ns{font-weight:600}.swagger-ui .fw7-ns{font-weight:700}.swagger-ui .fw8-ns{font-weight:800}.swagger-ui .fw9-ns{font-weight:900}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .normal-m{font-weight:400}.swagger-ui .b-m{font-weight:700}.swagger-ui .fw1-m{font-weight:100}.swagger-ui .fw2-m{font-weight:200}.swagger-ui .fw3-m{font-weight:300}.swagger-ui .fw4-m{font-weight:400}.swagger-ui .fw5-m{font-weight:500}.swagger-ui .fw6-m{font-weight:600}.swagger-ui .fw7-m{font-weight:700}.swagger-ui .fw8-m{font-weight:800}.swagger-ui .fw9-m{font-weight:900}}@media screen and (min-width:60em){.swagger-ui .normal-l{font-weight:400}.swagger-ui .b-l{font-weight:700}.swagger-ui .fw1-l{font-weight:100}.swagger-ui .fw2-l{font-weight:200}.swagger-ui .fw3-l{font-weight:300}.swagger-ui .fw4-l{font-weight:400}.swagger-ui .fw5-l{font-weight:500}.swagger-ui .fw6-l{font-weight:600}.swagger-ui .fw7-l{font-weight:700}.swagger-ui .fw8-l{font-weight:800}.swagger-ui .fw9-l{font-weight:900}}.swagger-ui .input-reset{-webkit-appearance:none;-moz-appearance:none}.swagger-ui .button-reset::-moz-focus-inner,.swagger-ui .input-reset::-moz-focus-inner{border:0;padding:0}.swagger-ui .h1{height:1rem}.swagger-ui .h2{height:2rem}.swagger-ui .h3{height:4rem}.swagger-ui .h4{height:8rem}.swagger-ui .h5{height:16rem}.swagger-ui .h-25{height:25%}.swagger-ui .h-50{height:50%}.swagger-ui .h-75{height:75%}.swagger-ui .h-100{height:100%}.swagger-ui .min-h-100{min-height:100%}.swagger-ui .vh-25{height:25vh}.swagger-ui .vh-50{height:50vh}.swagger-ui .vh-75{height:75vh}.swagger-ui .vh-100{height:100vh}.swagger-ui .min-vh-100{min-height:100vh}.swagger-ui .h-auto{height:auto}.swagger-ui .h-inherit{height:inherit}@media screen and (min-width:30em){.swagger-ui .h1-ns{height:1rem}.swagger-ui .h2-ns{height:2rem}.swagger-ui .h3-ns{height:4rem}.swagger-ui .h4-ns{height:8rem}.swagger-ui .h5-ns{height:16rem}.swagger-ui .h-25-ns{height:25%}.swagger-ui .h-50-ns{height:50%}.swagger-ui .h-75-ns{height:75%}.swagger-ui .h-100-ns{height:100%}.swagger-ui .min-h-100-ns{min-height:100%}.swagger-ui .vh-25-ns{height:25vh}.swagger-ui .vh-50-ns{height:50vh}.swagger-ui .vh-75-ns{height:75vh}.swagger-ui .vh-100-ns{height:100vh}.swagger-ui .min-vh-100-ns{min-height:100vh}.swagger-ui .h-auto-ns{height:auto}.swagger-ui .h-inherit-ns{height:inherit}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .h1-m{height:1rem}.swagger-ui .h2-m{height:2rem}.swagger-ui .h3-m{height:4rem}.swagger-ui .h4-m{height:8rem}.swagger-ui .h5-m{height:16rem}.swagger-ui .h-25-m{height:25%}.swagger-ui .h-50-m{height:50%}.swagger-ui .h-75-m{height:75%}.swagger-ui .h-100-m{height:100%}.swagger-ui .min-h-100-m{min-height:100%}.swagger-ui .vh-25-m{height:25vh}.swagger-ui .vh-50-m{height:50vh}.swagger-ui .vh-75-m{height:75vh}.swagger-ui .vh-100-m{height:100vh}.swagger-ui .min-vh-100-m{min-height:100vh}.swagger-ui .h-auto-m{height:auto}.swagger-ui .h-inherit-m{height:inherit}}@media screen and (min-width:60em){.swagger-ui .h1-l{height:1rem}.swagger-ui .h2-l{height:2rem}.swagger-ui .h3-l{height:4rem}.swagger-ui .h4-l{height:8rem}.swagger-ui .h5-l{height:16rem}.swagger-ui .h-25-l{height:25%}.swagger-ui .h-50-l{height:50%}.swagger-ui .h-75-l{height:75%}.swagger-ui .h-100-l{height:100%}.swagger-ui .min-h-100-l{min-height:100%}.swagger-ui .vh-25-l{height:25vh}.swagger-ui .vh-50-l{height:50vh}.swagger-ui .vh-75-l{height:75vh}.swagger-ui .vh-100-l{height:100vh}.swagger-ui .min-vh-100-l{min-height:100vh}.swagger-ui .h-auto-l{height:auto}.swagger-ui .h-inherit-l{height:inherit}}.swagger-ui .tracked{letter-spacing:.1em}.swagger-ui .tracked-tight{letter-spacing:-.05em}.swagger-ui .tracked-mega{letter-spacing:.25em}@media screen and (min-width:30em){.swagger-ui .tracked-ns{letter-spacing:.1em}.swagger-ui .tracked-tight-ns{letter-spacing:-.05em}.swagger-ui .tracked-mega-ns{letter-spacing:.25em}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .tracked-m{letter-spacing:.1em}.swagger-ui .tracked-tight-m{letter-spacing:-.05em}.swagger-ui .tracked-mega-m{letter-spacing:.25em}}@media screen and (min-width:60em){.swagger-ui .tracked-l{letter-spacing:.1em}.swagger-ui .tracked-tight-l{letter-spacing:-.05em}.swagger-ui .tracked-mega-l{letter-spacing:.25em}}.swagger-ui .lh-solid{line-height:1}.swagger-ui .lh-title{line-height:1.25}.swagger-ui .lh-copy{line-height:1.5}@media screen and (min-width:30em){.swagger-ui .lh-solid-ns{line-height:1}.swagger-ui .lh-title-ns{line-height:1.25}.swagger-ui .lh-copy-ns{line-height:1.5}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .lh-solid-m{line-height:1}.swagger-ui .lh-title-m{line-height:1.25}.swagger-ui .lh-copy-m{line-height:1.5}}@media screen and (min-width:60em){.swagger-ui .lh-solid-l{line-height:1}.swagger-ui .lh-title-l{line-height:1.25}.swagger-ui .lh-copy-l{line-height:1.5}}.swagger-ui .link{text-decoration:none}.swagger-ui .link,.swagger-ui .link:active,.swagger-ui .link:focus,.swagger-ui .link:hover,.swagger-ui .link:link,.swagger-ui .link:visited{transition:color .15s ease-in}.swagger-ui .link:focus{outline:1px dotted currentColor}.swagger-ui .list{list-style-type:none}.swagger-ui .mw-100{max-width:100%}.swagger-ui .mw1{max-width:1rem}.swagger-ui .mw2{max-width:2rem}.swagger-ui .mw3{max-width:4rem}.swagger-ui .mw4{max-width:8rem}.swagger-ui .mw5{max-width:16rem}.swagger-ui .mw6{max-width:32rem}.swagger-ui .mw7{max-width:48rem}.swagger-ui .mw8{max-width:64rem}.swagger-ui .mw9{max-width:96rem}.swagger-ui .mw-none{max-width:none}@media screen and (min-width:30em){.swagger-ui .mw-100-ns{max-width:100%}.swagger-ui .mw1-ns{max-width:1rem}.swagger-ui .mw2-ns{max-width:2rem}.swagger-ui .mw3-ns{max-width:4rem}.swagger-ui .mw4-ns{max-width:8rem}.swagger-ui .mw5-ns{max-width:16rem}.swagger-ui .mw6-ns{max-width:32rem}.swagger-ui .mw7-ns{max-width:48rem}.swagger-ui .mw8-ns{max-width:64rem}.swagger-ui .mw9-ns{max-width:96rem}.swagger-ui .mw-none-ns{max-width:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .mw-100-m{max-width:100%}.swagger-ui .mw1-m{max-width:1rem}.swagger-ui .mw2-m{max-width:2rem}.swagger-ui .mw3-m{max-width:4rem}.swagger-ui .mw4-m{max-width:8rem}.swagger-ui .mw5-m{max-width:16rem}.swagger-ui .mw6-m{max-width:32rem}.swagger-ui .mw7-m{max-width:48rem}.swagger-ui .mw8-m{max-width:64rem}.swagger-ui .mw9-m{max-width:96rem}.swagger-ui .mw-none-m{max-width:none}}@media screen and (min-width:60em){.swagger-ui .mw-100-l{max-width:100%}.swagger-ui .mw1-l{max-width:1rem}.swagger-ui .mw2-l{max-width:2rem}.swagger-ui .mw3-l{max-width:4rem}.swagger-ui .mw4-l{max-width:8rem}.swagger-ui .mw5-l{max-width:16rem}.swagger-ui .mw6-l{max-width:32rem}.swagger-ui .mw7-l{max-width:48rem}.swagger-ui .mw8-l{max-width:64rem}.swagger-ui .mw9-l{max-width:96rem}.swagger-ui .mw-none-l{max-width:none}}.swagger-ui .w1{width:1rem}.swagger-ui .w2{width:2rem}.swagger-ui .w3{width:4rem}.swagger-ui .w4{width:8rem}.swagger-ui .w5{width:16rem}.swagger-ui .w-10{width:10%}.swagger-ui .w-20{width:20%}.swagger-ui .w-25{width:25%}.swagger-ui .w-30{width:30%}.swagger-ui .w-33{width:33%}.swagger-ui .w-34{width:34%}.swagger-ui .w-40{width:40%}.swagger-ui .w-50{width:50%}.swagger-ui .w-60{width:60%}.swagger-ui .w-70{width:70%}.swagger-ui .w-75{width:75%}.swagger-ui .w-80{width:80%}.swagger-ui .w-90{width:90%}.swagger-ui .w-100{width:100%}.swagger-ui .w-third{width:33.3333333333%}.swagger-ui .w-two-thirds{width:66.6666666667%}.swagger-ui .w-auto{width:auto}@media screen and (min-width:30em){.swagger-ui .w1-ns{width:1rem}.swagger-ui .w2-ns{width:2rem}.swagger-ui .w3-ns{width:4rem}.swagger-ui .w4-ns{width:8rem}.swagger-ui .w5-ns{width:16rem}.swagger-ui .w-10-ns{width:10%}.swagger-ui .w-20-ns{width:20%}.swagger-ui .w-25-ns{width:25%}.swagger-ui .w-30-ns{width:30%}.swagger-ui .w-33-ns{width:33%}.swagger-ui .w-34-ns{width:34%}.swagger-ui .w-40-ns{width:40%}.swagger-ui .w-50-ns{width:50%}.swagger-ui .w-60-ns{width:60%}.swagger-ui .w-70-ns{width:70%}.swagger-ui .w-75-ns{width:75%}.swagger-ui .w-80-ns{width:80%}.swagger-ui .w-90-ns{width:90%}.swagger-ui .w-100-ns{width:100%}.swagger-ui .w-third-ns{width:33.3333333333%}.swagger-ui .w-two-thirds-ns{width:66.6666666667%}.swagger-ui .w-auto-ns{width:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .w1-m{width:1rem}.swagger-ui .w2-m{width:2rem}.swagger-ui .w3-m{width:4rem}.swagger-ui .w4-m{width:8rem}.swagger-ui .w5-m{width:16rem}.swagger-ui .w-10-m{width:10%}.swagger-ui .w-20-m{width:20%}.swagger-ui .w-25-m{width:25%}.swagger-ui .w-30-m{width:30%}.swagger-ui .w-33-m{width:33%}.swagger-ui .w-34-m{width:34%}.swagger-ui .w-40-m{width:40%}.swagger-ui .w-50-m{width:50%}.swagger-ui .w-60-m{width:60%}.swagger-ui .w-70-m{width:70%}.swagger-ui .w-75-m{width:75%}.swagger-ui .w-80-m{width:80%}.swagger-ui .w-90-m{width:90%}.swagger-ui .w-100-m{width:100%}.swagger-ui .w-third-m{width:33.3333333333%}.swagger-ui .w-two-thirds-m{width:66.6666666667%}.swagger-ui .w-auto-m{width:auto}}@media screen and (min-width:60em){.swagger-ui .w1-l{width:1rem}.swagger-ui .w2-l{width:2rem}.swagger-ui .w3-l{width:4rem}.swagger-ui .w4-l{width:8rem}.swagger-ui .w5-l{width:16rem}.swagger-ui .w-10-l{width:10%}.swagger-ui .w-20-l{width:20%}.swagger-ui .w-25-l{width:25%}.swagger-ui .w-30-l{width:30%}.swagger-ui .w-33-l{width:33%}.swagger-ui .w-34-l{width:34%}.swagger-ui .w-40-l{width:40%}.swagger-ui .w-50-l{width:50%}.swagger-ui .w-60-l{width:60%}.swagger-ui .w-70-l{width:70%}.swagger-ui .w-75-l{width:75%}.swagger-ui .w-80-l{width:80%}.swagger-ui .w-90-l{width:90%}.swagger-ui .w-100-l{width:100%}.swagger-ui .w-third-l{width:33.3333333333%}.swagger-ui .w-two-thirds-l{width:66.6666666667%}.swagger-ui .w-auto-l{width:auto}}.swagger-ui .overflow-visible{overflow:visible}.swagger-ui .overflow-hidden{overflow:hidden}.swagger-ui .overflow-scroll{overflow:scroll}.swagger-ui .overflow-auto{overflow:auto}.swagger-ui .overflow-x-visible{overflow-x:visible}.swagger-ui .overflow-x-hidden{overflow-x:hidden}.swagger-ui .overflow-x-scroll{overflow-x:scroll}.swagger-ui .overflow-x-auto{overflow-x:auto}.swagger-ui .overflow-y-visible{overflow-y:visible}.swagger-ui .overflow-y-hidden{overflow-y:hidden}.swagger-ui .overflow-y-scroll{overflow-y:scroll}.swagger-ui .overflow-y-auto{overflow-y:auto}@media screen and (min-width:30em){.swagger-ui .overflow-visible-ns{overflow:visible}.swagger-ui .overflow-hidden-ns{overflow:hidden}.swagger-ui .overflow-scroll-ns{overflow:scroll}.swagger-ui .overflow-auto-ns{overflow:auto}.swagger-ui .overflow-x-visible-ns{overflow-x:visible}.swagger-ui .overflow-x-hidden-ns{overflow-x:hidden}.swagger-ui .overflow-x-scroll-ns{overflow-x:scroll}.swagger-ui .overflow-x-auto-ns{overflow-x:auto}.swagger-ui .overflow-y-visible-ns{overflow-y:visible}.swagger-ui .overflow-y-hidden-ns{overflow-y:hidden}.swagger-ui .overflow-y-scroll-ns{overflow-y:scroll}.swagger-ui .overflow-y-auto-ns{overflow-y:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .overflow-visible-m{overflow:visible}.swagger-ui .overflow-hidden-m{overflow:hidden}.swagger-ui .overflow-scroll-m{overflow:scroll}.swagger-ui .overflow-auto-m{overflow:auto}.swagger-ui .overflow-x-visible-m{overflow-x:visible}.swagger-ui .overflow-x-hidden-m{overflow-x:hidden}.swagger-ui .overflow-x-scroll-m{overflow-x:scroll}.swagger-ui .overflow-x-auto-m{overflow-x:auto}.swagger-ui .overflow-y-visible-m{overflow-y:visible}.swagger-ui .overflow-y-hidden-m{overflow-y:hidden}.swagger-ui .overflow-y-scroll-m{overflow-y:scroll}.swagger-ui .overflow-y-auto-m{overflow-y:auto}}@media screen and (min-width:60em){.swagger-ui .overflow-visible-l{overflow:visible}.swagger-ui .overflow-hidden-l{overflow:hidden}.swagger-ui .overflow-scroll-l{overflow:scroll}.swagger-ui .overflow-auto-l{overflow:auto}.swagger-ui .overflow-x-visible-l{overflow-x:visible}.swagger-ui .overflow-x-hidden-l{overflow-x:hidden}.swagger-ui .overflow-x-scroll-l{overflow-x:scroll}.swagger-ui .overflow-x-auto-l{overflow-x:auto}.swagger-ui .overflow-y-visible-l{overflow-y:visible}.swagger-ui .overflow-y-hidden-l{overflow-y:hidden}.swagger-ui .overflow-y-scroll-l{overflow-y:scroll}.swagger-ui .overflow-y-auto-l{overflow-y:auto}}.swagger-ui .static{position:static}.swagger-ui .relative{position:relative}.swagger-ui .absolute{position:absolute}.swagger-ui .fixed{position:fixed}@media screen and (min-width:30em){.swagger-ui .static-ns{position:static}.swagger-ui .relative-ns{position:relative}.swagger-ui .absolute-ns{position:absolute}.swagger-ui .fixed-ns{position:fixed}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .static-m{position:static}.swagger-ui .relative-m{position:relative}.swagger-ui .absolute-m{position:absolute}.swagger-ui .fixed-m{position:fixed}}@media screen and (min-width:60em){.swagger-ui .static-l{position:static}.swagger-ui .relative-l{position:relative}.swagger-ui .absolute-l{position:absolute}.swagger-ui .fixed-l{position:fixed}}.swagger-ui .o-100{opacity:1}.swagger-ui .o-90{opacity:.9}.swagger-ui .o-80{opacity:.8}.swagger-ui .o-70{opacity:.7}.swagger-ui .o-60{opacity:.6}.swagger-ui .o-50{opacity:.5}.swagger-ui .o-40{opacity:.4}.swagger-ui .o-30{opacity:.3}.swagger-ui .o-20{opacity:.2}.swagger-ui .o-10{opacity:.1}.swagger-ui .o-05{opacity:.05}.swagger-ui .o-025{opacity:.025}.swagger-ui .o-0{opacity:0}.swagger-ui .rotate-45{transform:rotate(45deg)}.swagger-ui .rotate-90{transform:rotate(90deg)}.swagger-ui .rotate-135{transform:rotate(135deg)}.swagger-ui .rotate-180{transform:rotate(180deg)}.swagger-ui .rotate-225{transform:rotate(225deg)}.swagger-ui .rotate-270{transform:rotate(270deg)}.swagger-ui .rotate-315{transform:rotate(315deg)}@media screen and (min-width:30em){.swagger-ui .rotate-45-ns{transform:rotate(45deg)}.swagger-ui .rotate-90-ns{transform:rotate(90deg)}.swagger-ui .rotate-135-ns{transform:rotate(135deg)}.swagger-ui .rotate-180-ns{transform:rotate(180deg)}.swagger-ui .rotate-225-ns{transform:rotate(225deg)}.swagger-ui .rotate-270-ns{transform:rotate(270deg)}.swagger-ui .rotate-315-ns{transform:rotate(315deg)}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .rotate-45-m{transform:rotate(45deg)}.swagger-ui .rotate-90-m{transform:rotate(90deg)}.swagger-ui .rotate-135-m{transform:rotate(135deg)}.swagger-ui .rotate-180-m{transform:rotate(180deg)}.swagger-ui .rotate-225-m{transform:rotate(225deg)}.swagger-ui .rotate-270-m{transform:rotate(270deg)}.swagger-ui .rotate-315-m{transform:rotate(315deg)}}@media screen and (min-width:60em){.swagger-ui .rotate-45-l{transform:rotate(45deg)}.swagger-ui .rotate-90-l{transform:rotate(90deg)}.swagger-ui .rotate-135-l{transform:rotate(135deg)}.swagger-ui .rotate-180-l{transform:rotate(180deg)}.swagger-ui .rotate-225-l{transform:rotate(225deg)}.swagger-ui .rotate-270-l{transform:rotate(270deg)}.swagger-ui .rotate-315-l{transform:rotate(315deg)}}.swagger-ui .black-90{color:rgba(0,0,0,.9)}.swagger-ui .black-80{color:rgba(0,0,0,.8)}.swagger-ui .black-70{color:rgba(0,0,0,.7)}.swagger-ui .black-60{color:rgba(0,0,0,.6)}.swagger-ui .black-50{color:rgba(0,0,0,.5)}.swagger-ui .black-40{color:rgba(0,0,0,.4)}.swagger-ui .black-30{color:rgba(0,0,0,.3)}.swagger-ui .black-20{color:rgba(0,0,0,.2)}.swagger-ui .black-10{color:rgba(0,0,0,.1)}.swagger-ui .black-05{color:rgba(0,0,0,.05)}.swagger-ui .white-90{color:hsla(0,0%,100%,.9)}.swagger-ui .white-80{color:hsla(0,0%,100%,.8)}.swagger-ui .white-70{color:hsla(0,0%,100%,.7)}.swagger-ui .white-60{color:hsla(0,0%,100%,.6)}.swagger-ui .white-50{color:hsla(0,0%,100%,.5)}.swagger-ui .white-40{color:hsla(0,0%,100%,.4)}.swagger-ui .white-30{color:hsla(0,0%,100%,.3)}.swagger-ui .white-20{color:hsla(0,0%,100%,.2)}.swagger-ui .white-10{color:hsla(0,0%,100%,.1)}.swagger-ui .black{color:#000}.swagger-ui .near-black{color:#111}.swagger-ui .dark-gray{color:#333}.swagger-ui .mid-gray{color:#555}.swagger-ui .gray{color:#777}.swagger-ui .silver{color:#999}.swagger-ui .light-silver{color:#aaa}.swagger-ui .moon-gray{color:#ccc}.swagger-ui .light-gray{color:#eee}.swagger-ui .near-white{color:#f4f4f4}.swagger-ui .white{color:#fff}.swagger-ui .dark-red{color:#e7040f}.swagger-ui .red{color:#ff4136}.swagger-ui .light-red{color:#ff725c}.swagger-ui .orange{color:#ff6300}.swagger-ui .gold{color:#ffb700}.swagger-ui .yellow{color:gold}.swagger-ui .light-yellow{color:#fbf1a9}.swagger-ui .purple{color:#5e2ca5}.swagger-ui .light-purple{color:#a463f2}.swagger-ui .dark-pink{color:#d5008f}.swagger-ui .hot-pink{color:#ff41b4}.swagger-ui .pink{color:#ff80cc}.swagger-ui .light-pink{color:#ffa3d7}.swagger-ui .dark-green{color:#137752}.swagger-ui .green{color:#19a974}.swagger-ui .light-green{color:#9eebcf}.swagger-ui .navy{color:#001b44}.swagger-ui .dark-blue{color:#00449e}.swagger-ui .blue{color:#357edd}.swagger-ui .light-blue{color:#96ccff}.swagger-ui .lightest-blue{color:#cdecff}.swagger-ui .washed-blue{color:#f6fffe}.swagger-ui .washed-green{color:#e8fdf5}.swagger-ui .washed-yellow{color:#fffceb}.swagger-ui .washed-red{color:#ffdfdf}.swagger-ui .color-inherit{color:inherit}.swagger-ui .bg-black-90{background-color:rgba(0,0,0,.9)}.swagger-ui .bg-black-80{background-color:rgba(0,0,0,.8)}.swagger-ui .bg-black-70{background-color:rgba(0,0,0,.7)}.swagger-ui .bg-black-60{background-color:rgba(0,0,0,.6)}.swagger-ui .bg-black-50{background-color:rgba(0,0,0,.5)}.swagger-ui .bg-black-40{background-color:rgba(0,0,0,.4)}.swagger-ui .bg-black-30{background-color:rgba(0,0,0,.3)}.swagger-ui .bg-black-20{background-color:rgba(0,0,0,.2)}.swagger-ui .bg-black-10{background-color:rgba(0,0,0,.1)}.swagger-ui .bg-black-05{background-color:rgba(0,0,0,.05)}.swagger-ui .bg-white-90{background-color:hsla(0,0%,100%,.9)}.swagger-ui .bg-white-80{background-color:hsla(0,0%,100%,.8)}.swagger-ui .bg-white-70{background-color:hsla(0,0%,100%,.7)}.swagger-ui .bg-white-60{background-color:hsla(0,0%,100%,.6)}.swagger-ui .bg-white-50{background-color:hsla(0,0%,100%,.5)}.swagger-ui .bg-white-40{background-color:hsla(0,0%,100%,.4)}.swagger-ui .bg-white-30{background-color:hsla(0,0%,100%,.3)}.swagger-ui .bg-white-20{background-color:hsla(0,0%,100%,.2)}.swagger-ui .bg-white-10{background-color:hsla(0,0%,100%,.1)}.swagger-ui .bg-black{background-color:#000}.swagger-ui .bg-near-black{background-color:#111}.swagger-ui .bg-dark-gray{background-color:#333}.swagger-ui .bg-mid-gray{background-color:#555}.swagger-ui .bg-gray{background-color:#777}.swagger-ui .bg-silver{background-color:#999}.swagger-ui .bg-light-silver{background-color:#aaa}.swagger-ui .bg-moon-gray{background-color:#ccc}.swagger-ui .bg-light-gray{background-color:#eee}.swagger-ui .bg-near-white{background-color:#f4f4f4}.swagger-ui .bg-white{background-color:#fff}.swagger-ui .bg-transparent{background-color:transparent}.swagger-ui .bg-dark-red{background-color:#e7040f}.swagger-ui .bg-red{background-color:#ff4136}.swagger-ui .bg-light-red{background-color:#ff725c}.swagger-ui .bg-orange{background-color:#ff6300}.swagger-ui .bg-gold{background-color:#ffb700}.swagger-ui .bg-yellow{background-color:gold}.swagger-ui .bg-light-yellow{background-color:#fbf1a9}.swagger-ui .bg-purple{background-color:#5e2ca5}.swagger-ui .bg-light-purple{background-color:#a463f2}.swagger-ui .bg-dark-pink{background-color:#d5008f}.swagger-ui .bg-hot-pink{background-color:#ff41b4}.swagger-ui .bg-pink{background-color:#ff80cc}.swagger-ui .bg-light-pink{background-color:#ffa3d7}.swagger-ui .bg-dark-green{background-color:#137752}.swagger-ui .bg-green{background-color:#19a974}.swagger-ui .bg-light-green{background-color:#9eebcf}.swagger-ui .bg-navy{background-color:#001b44}.swagger-ui .bg-dark-blue{background-color:#00449e}.swagger-ui .bg-blue{background-color:#357edd}.swagger-ui .bg-light-blue{background-color:#96ccff}.swagger-ui .bg-lightest-blue{background-color:#cdecff}.swagger-ui .bg-washed-blue{background-color:#f6fffe}.swagger-ui .bg-washed-green{background-color:#e8fdf5}.swagger-ui .bg-washed-yellow{background-color:#fffceb}.swagger-ui .bg-washed-red{background-color:#ffdfdf}.swagger-ui .bg-inherit{background-color:inherit}.swagger-ui .hover-black:focus,.swagger-ui .hover-black:hover{color:#000}.swagger-ui .hover-near-black:focus,.swagger-ui .hover-near-black:hover{color:#111}.swagger-ui .hover-dark-gray:focus,.swagger-ui .hover-dark-gray:hover{color:#333}.swagger-ui .hover-mid-gray:focus,.swagger-ui .hover-mid-gray:hover{color:#555}.swagger-ui .hover-gray:focus,.swagger-ui .hover-gray:hover{color:#777}.swagger-ui .hover-silver:focus,.swagger-ui .hover-silver:hover{color:#999}.swagger-ui .hover-light-silver:focus,.swagger-ui .hover-light-silver:hover{color:#aaa}.swagger-ui .hover-moon-gray:focus,.swagger-ui .hover-moon-gray:hover{color:#ccc}.swagger-ui .hover-light-gray:focus,.swagger-ui .hover-light-gray:hover{color:#eee}.swagger-ui .hover-near-white:focus,.swagger-ui .hover-near-white:hover{color:#f4f4f4}.swagger-ui .hover-white:focus,.swagger-ui .hover-white:hover{color:#fff}.swagger-ui .hover-black-90:focus,.swagger-ui .hover-black-90:hover{color:rgba(0,0,0,.9)}.swagger-ui .hover-black-80:focus,.swagger-ui .hover-black-80:hover{color:rgba(0,0,0,.8)}.swagger-ui .hover-black-70:focus,.swagger-ui .hover-black-70:hover{color:rgba(0,0,0,.7)}.swagger-ui .hover-black-60:focus,.swagger-ui .hover-black-60:hover{color:rgba(0,0,0,.6)}.swagger-ui .hover-black-50:focus,.swagger-ui .hover-black-50:hover{color:rgba(0,0,0,.5)}.swagger-ui .hover-black-40:focus,.swagger-ui .hover-black-40:hover{color:rgba(0,0,0,.4)}.swagger-ui .hover-black-30:focus,.swagger-ui .hover-black-30:hover{color:rgba(0,0,0,.3)}.swagger-ui .hover-black-20:focus,.swagger-ui .hover-black-20:hover{color:rgba(0,0,0,.2)}.swagger-ui .hover-black-10:focus,.swagger-ui .hover-black-10:hover{color:rgba(0,0,0,.1)}.swagger-ui .hover-white-90:focus,.swagger-ui .hover-white-90:hover{color:hsla(0,0%,100%,.9)}.swagger-ui .hover-white-80:focus,.swagger-ui .hover-white-80:hover{color:hsla(0,0%,100%,.8)}.swagger-ui .hover-white-70:focus,.swagger-ui .hover-white-70:hover{color:hsla(0,0%,100%,.7)}.swagger-ui .hover-white-60:focus,.swagger-ui .hover-white-60:hover{color:hsla(0,0%,100%,.6)}.swagger-ui .hover-white-50:focus,.swagger-ui .hover-white-50:hover{color:hsla(0,0%,100%,.5)}.swagger-ui .hover-white-40:focus,.swagger-ui .hover-white-40:hover{color:hsla(0,0%,100%,.4)}.swagger-ui .hover-white-30:focus,.swagger-ui .hover-white-30:hover{color:hsla(0,0%,100%,.3)}.swagger-ui .hover-white-20:focus,.swagger-ui .hover-white-20:hover{color:hsla(0,0%,100%,.2)}.swagger-ui .hover-white-10:focus,.swagger-ui .hover-white-10:hover{color:hsla(0,0%,100%,.1)}.swagger-ui .hover-inherit:focus,.swagger-ui .hover-inherit:hover{color:inherit}.swagger-ui .hover-bg-black:focus,.swagger-ui .hover-bg-black:hover{background-color:#000}.swagger-ui .hover-bg-near-black:focus,.swagger-ui .hover-bg-near-black:hover{background-color:#111}.swagger-ui .hover-bg-dark-gray:focus,.swagger-ui .hover-bg-dark-gray:hover{background-color:#333}.swagger-ui .hover-bg-mid-gray:focus,.swagger-ui .hover-bg-mid-gray:hover{background-color:#555}.swagger-ui .hover-bg-gray:focus,.swagger-ui .hover-bg-gray:hover{background-color:#777}.swagger-ui .hover-bg-silver:focus,.swagger-ui .hover-bg-silver:hover{background-color:#999}.swagger-ui .hover-bg-light-silver:focus,.swagger-ui .hover-bg-light-silver:hover{background-color:#aaa}.swagger-ui .hover-bg-moon-gray:focus,.swagger-ui .hover-bg-moon-gray:hover{background-color:#ccc}.swagger-ui .hover-bg-light-gray:focus,.swagger-ui .hover-bg-light-gray:hover{background-color:#eee}.swagger-ui .hover-bg-near-white:focus,.swagger-ui .hover-bg-near-white:hover{background-color:#f4f4f4}.swagger-ui .hover-bg-white:focus,.swagger-ui .hover-bg-white:hover{background-color:#fff}.swagger-ui .hover-bg-transparent:focus,.swagger-ui .hover-bg-transparent:hover{background-color:transparent}.swagger-ui .hover-bg-black-90:focus,.swagger-ui .hover-bg-black-90:hover{background-color:rgba(0,0,0,.9)}.swagger-ui .hover-bg-black-80:focus,.swagger-ui .hover-bg-black-80:hover{background-color:rgba(0,0,0,.8)}.swagger-ui .hover-bg-black-70:focus,.swagger-ui .hover-bg-black-70:hover{background-color:rgba(0,0,0,.7)}.swagger-ui .hover-bg-black-60:focus,.swagger-ui .hover-bg-black-60:hover{background-color:rgba(0,0,0,.6)}.swagger-ui .hover-bg-black-50:focus,.swagger-ui .hover-bg-black-50:hover{background-color:rgba(0,0,0,.5)}.swagger-ui .hover-bg-black-40:focus,.swagger-ui .hover-bg-black-40:hover{background-color:rgba(0,0,0,.4)}.swagger-ui .hover-bg-black-30:focus,.swagger-ui .hover-bg-black-30:hover{background-color:rgba(0,0,0,.3)}.swagger-ui .hover-bg-black-20:focus,.swagger-ui .hover-bg-black-20:hover{background-color:rgba(0,0,0,.2)}.swagger-ui .hover-bg-black-10:focus,.swagger-ui .hover-bg-black-10:hover{background-color:rgba(0,0,0,.1)}.swagger-ui .hover-bg-white-90:focus,.swagger-ui .hover-bg-white-90:hover{background-color:hsla(0,0%,100%,.9)}.swagger-ui .hover-bg-white-80:focus,.swagger-ui .hover-bg-white-80:hover{background-color:hsla(0,0%,100%,.8)}.swagger-ui .hover-bg-white-70:focus,.swagger-ui .hover-bg-white-70:hover{background-color:hsla(0,0%,100%,.7)}.swagger-ui .hover-bg-white-60:focus,.swagger-ui .hover-bg-white-60:hover{background-color:hsla(0,0%,100%,.6)}.swagger-ui .hover-bg-white-50:focus,.swagger-ui .hover-bg-white-50:hover{background-color:hsla(0,0%,100%,.5)}.swagger-ui .hover-bg-white-40:focus,.swagger-ui .hover-bg-white-40:hover{background-color:hsla(0,0%,100%,.4)}.swagger-ui .hover-bg-white-30:focus,.swagger-ui .hover-bg-white-30:hover{background-color:hsla(0,0%,100%,.3)}.swagger-ui .hover-bg-white-20:focus,.swagger-ui .hover-bg-white-20:hover{background-color:hsla(0,0%,100%,.2)}.swagger-ui .hover-bg-white-10:focus,.swagger-ui .hover-bg-white-10:hover{background-color:hsla(0,0%,100%,.1)}.swagger-ui .hover-dark-red:focus,.swagger-ui .hover-dark-red:hover{color:#e7040f}.swagger-ui .hover-red:focus,.swagger-ui .hover-red:hover{color:#ff4136}.swagger-ui .hover-light-red:focus,.swagger-ui .hover-light-red:hover{color:#ff725c}.swagger-ui .hover-orange:focus,.swagger-ui .hover-orange:hover{color:#ff6300}.swagger-ui .hover-gold:focus,.swagger-ui .hover-gold:hover{color:#ffb700}.swagger-ui .hover-yellow:focus,.swagger-ui .hover-yellow:hover{color:gold}.swagger-ui .hover-light-yellow:focus,.swagger-ui .hover-light-yellow:hover{color:#fbf1a9}.swagger-ui .hover-purple:focus,.swagger-ui .hover-purple:hover{color:#5e2ca5}.swagger-ui .hover-light-purple:focus,.swagger-ui .hover-light-purple:hover{color:#a463f2}.swagger-ui .hover-dark-pink:focus,.swagger-ui .hover-dark-pink:hover{color:#d5008f}.swagger-ui .hover-hot-pink:focus,.swagger-ui .hover-hot-pink:hover{color:#ff41b4}.swagger-ui .hover-pink:focus,.swagger-ui .hover-pink:hover{color:#ff80cc}.swagger-ui .hover-light-pink:focus,.swagger-ui .hover-light-pink:hover{color:#ffa3d7}.swagger-ui .hover-dark-green:focus,.swagger-ui .hover-dark-green:hover{color:#137752}.swagger-ui .hover-green:focus,.swagger-ui .hover-green:hover{color:#19a974}.swagger-ui .hover-light-green:focus,.swagger-ui .hover-light-green:hover{color:#9eebcf}.swagger-ui .hover-navy:focus,.swagger-ui .hover-navy:hover{color:#001b44}.swagger-ui .hover-dark-blue:focus,.swagger-ui .hover-dark-blue:hover{color:#00449e}.swagger-ui .hover-blue:focus,.swagger-ui .hover-blue:hover{color:#357edd}.swagger-ui .hover-light-blue:focus,.swagger-ui .hover-light-blue:hover{color:#96ccff}.swagger-ui .hover-lightest-blue:focus,.swagger-ui .hover-lightest-blue:hover{color:#cdecff}.swagger-ui .hover-washed-blue:focus,.swagger-ui .hover-washed-blue:hover{color:#f6fffe}.swagger-ui .hover-washed-green:focus,.swagger-ui .hover-washed-green:hover{color:#e8fdf5}.swagger-ui .hover-washed-yellow:focus,.swagger-ui .hover-washed-yellow:hover{color:#fffceb}.swagger-ui .hover-washed-red:focus,.swagger-ui .hover-washed-red:hover{color:#ffdfdf}.swagger-ui .hover-bg-dark-red:focus,.swagger-ui .hover-bg-dark-red:hover{background-color:#e7040f}.swagger-ui .hover-bg-red:focus,.swagger-ui .hover-bg-red:hover{background-color:#ff4136}.swagger-ui .hover-bg-light-red:focus,.swagger-ui .hover-bg-light-red:hover{background-color:#ff725c}.swagger-ui .hover-bg-orange:focus,.swagger-ui .hover-bg-orange:hover{background-color:#ff6300}.swagger-ui .hover-bg-gold:focus,.swagger-ui .hover-bg-gold:hover{background-color:#ffb700}.swagger-ui .hover-bg-yellow:focus,.swagger-ui .hover-bg-yellow:hover{background-color:gold}.swagger-ui .hover-bg-light-yellow:focus,.swagger-ui .hover-bg-light-yellow:hover{background-color:#fbf1a9}.swagger-ui .hover-bg-purple:focus,.swagger-ui .hover-bg-purple:hover{background-color:#5e2ca5}.swagger-ui .hover-bg-light-purple:focus,.swagger-ui .hover-bg-light-purple:hover{background-color:#a463f2}.swagger-ui .hover-bg-dark-pink:focus,.swagger-ui .hover-bg-dark-pink:hover{background-color:#d5008f}.swagger-ui .hover-bg-hot-pink:focus,.swagger-ui .hover-bg-hot-pink:hover{background-color:#ff41b4}.swagger-ui .hover-bg-pink:focus,.swagger-ui .hover-bg-pink:hover{background-color:#ff80cc}.swagger-ui .hover-bg-light-pink:focus,.swagger-ui .hover-bg-light-pink:hover{background-color:#ffa3d7}.swagger-ui .hover-bg-dark-green:focus,.swagger-ui .hover-bg-dark-green:hover{background-color:#137752}.swagger-ui .hover-bg-green:focus,.swagger-ui .hover-bg-green:hover{background-color:#19a974}.swagger-ui .hover-bg-light-green:focus,.swagger-ui .hover-bg-light-green:hover{background-color:#9eebcf}.swagger-ui .hover-bg-navy:focus,.swagger-ui .hover-bg-navy:hover{background-color:#001b44}.swagger-ui .hover-bg-dark-blue:focus,.swagger-ui .hover-bg-dark-blue:hover{background-color:#00449e}.swagger-ui .hover-bg-blue:focus,.swagger-ui .hover-bg-blue:hover{background-color:#357edd}.swagger-ui .hover-bg-light-blue:focus,.swagger-ui .hover-bg-light-blue:hover{background-color:#96ccff}.swagger-ui .hover-bg-lightest-blue:focus,.swagger-ui .hover-bg-lightest-blue:hover{background-color:#cdecff}.swagger-ui .hover-bg-washed-blue:focus,.swagger-ui .hover-bg-washed-blue:hover{background-color:#f6fffe}.swagger-ui .hover-bg-washed-green:focus,.swagger-ui .hover-bg-washed-green:hover{background-color:#e8fdf5}.swagger-ui .hover-bg-washed-yellow:focus,.swagger-ui .hover-bg-washed-yellow:hover{background-color:#fffceb}.swagger-ui .hover-bg-washed-red:focus,.swagger-ui .hover-bg-washed-red:hover{background-color:#ffdfdf}.swagger-ui .hover-bg-inherit:focus,.swagger-ui .hover-bg-inherit:hover{background-color:inherit}.swagger-ui .pa0{padding:0}.swagger-ui .pa1{padding:.25rem}.swagger-ui .pa2{padding:.5rem}.swagger-ui .pa3{padding:1rem}.swagger-ui .pa4{padding:2rem}.swagger-ui .pa5{padding:4rem}.swagger-ui .pa6{padding:8rem}.swagger-ui .pa7{padding:16rem}.swagger-ui .pl0{padding-left:0}.swagger-ui .pl1{padding-left:.25rem}.swagger-ui .pl2{padding-left:.5rem}.swagger-ui .pl3{padding-left:1rem}.swagger-ui .pl4{padding-left:2rem}.swagger-ui .pl5{padding-left:4rem}.swagger-ui .pl6{padding-left:8rem}.swagger-ui .pl7{padding-left:16rem}.swagger-ui .pr0{padding-right:0}.swagger-ui .pr1{padding-right:.25rem}.swagger-ui .pr2{padding-right:.5rem}.swagger-ui .pr3{padding-right:1rem}.swagger-ui .pr4{padding-right:2rem}.swagger-ui .pr5{padding-right:4rem}.swagger-ui .pr6{padding-right:8rem}.swagger-ui .pr7{padding-right:16rem}.swagger-ui .pb0{padding-bottom:0}.swagger-ui .pb1{padding-bottom:.25rem}.swagger-ui .pb2{padding-bottom:.5rem}.swagger-ui .pb3{padding-bottom:1rem}.swagger-ui .pb4{padding-bottom:2rem}.swagger-ui .pb5{padding-bottom:4rem}.swagger-ui .pb6{padding-bottom:8rem}.swagger-ui .pb7{padding-bottom:16rem}.swagger-ui .pt0{padding-top:0}.swagger-ui .pt1{padding-top:.25rem}.swagger-ui .pt2{padding-top:.5rem}.swagger-ui .pt3{padding-top:1rem}.swagger-ui .pt4{padding-top:2rem}.swagger-ui .pt5{padding-top:4rem}.swagger-ui .pt6{padding-top:8rem}.swagger-ui .pt7{padding-top:16rem}.swagger-ui .pv0{padding-bottom:0;padding-top:0}.swagger-ui .pv1{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0{padding-left:0;padding-right:0}.swagger-ui .ph1{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0{margin:0}.swagger-ui .ma1{margin:.25rem}.swagger-ui .ma2{margin:.5rem}.swagger-ui .ma3{margin:1rem}.swagger-ui .ma4{margin:2rem}.swagger-ui .ma5{margin:4rem}.swagger-ui .ma6{margin:8rem}.swagger-ui .ma7{margin:16rem}.swagger-ui .ml0{margin-left:0}.swagger-ui .ml1{margin-left:.25rem}.swagger-ui .ml2{margin-left:.5rem}.swagger-ui .ml3{margin-left:1rem}.swagger-ui .ml4{margin-left:2rem}.swagger-ui .ml5{margin-left:4rem}.swagger-ui .ml6{margin-left:8rem}.swagger-ui .ml7{margin-left:16rem}.swagger-ui .mr0{margin-right:0}.swagger-ui .mr1{margin-right:.25rem}.swagger-ui .mr2{margin-right:.5rem}.swagger-ui .mr3{margin-right:1rem}.swagger-ui .mr4{margin-right:2rem}.swagger-ui .mr5{margin-right:4rem}.swagger-ui .mr6{margin-right:8rem}.swagger-ui .mr7{margin-right:16rem}.swagger-ui .mb0{margin-bottom:0}.swagger-ui .mb1{margin-bottom:.25rem}.swagger-ui .mb2{margin-bottom:.5rem}.swagger-ui .mb3{margin-bottom:1rem}.swagger-ui .mb4{margin-bottom:2rem}.swagger-ui .mb5{margin-bottom:4rem}.swagger-ui .mb6{margin-bottom:8rem}.swagger-ui .mb7{margin-bottom:16rem}.swagger-ui .mt0{margin-top:0}.swagger-ui .mt1{margin-top:.25rem}.swagger-ui .mt2{margin-top:.5rem}.swagger-ui .mt3{margin-top:1rem}.swagger-ui .mt4{margin-top:2rem}.swagger-ui .mt5{margin-top:4rem}.swagger-ui .mt6{margin-top:8rem}.swagger-ui .mt7{margin-top:16rem}.swagger-ui .mv0{margin-bottom:0;margin-top:0}.swagger-ui .mv1{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0{margin-left:0;margin-right:0}.swagger-ui .mh1{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7{margin-left:16rem;margin-right:16rem}@media screen and (min-width:30em){.swagger-ui .pa0-ns{padding:0}.swagger-ui .pa1-ns{padding:.25rem}.swagger-ui .pa2-ns{padding:.5rem}.swagger-ui .pa3-ns{padding:1rem}.swagger-ui .pa4-ns{padding:2rem}.swagger-ui .pa5-ns{padding:4rem}.swagger-ui .pa6-ns{padding:8rem}.swagger-ui .pa7-ns{padding:16rem}.swagger-ui .pl0-ns{padding-left:0}.swagger-ui .pl1-ns{padding-left:.25rem}.swagger-ui .pl2-ns{padding-left:.5rem}.swagger-ui .pl3-ns{padding-left:1rem}.swagger-ui .pl4-ns{padding-left:2rem}.swagger-ui .pl5-ns{padding-left:4rem}.swagger-ui .pl6-ns{padding-left:8rem}.swagger-ui .pl7-ns{padding-left:16rem}.swagger-ui .pr0-ns{padding-right:0}.swagger-ui .pr1-ns{padding-right:.25rem}.swagger-ui .pr2-ns{padding-right:.5rem}.swagger-ui .pr3-ns{padding-right:1rem}.swagger-ui .pr4-ns{padding-right:2rem}.swagger-ui .pr5-ns{padding-right:4rem}.swagger-ui .pr6-ns{padding-right:8rem}.swagger-ui .pr7-ns{padding-right:16rem}.swagger-ui .pb0-ns{padding-bottom:0}.swagger-ui .pb1-ns{padding-bottom:.25rem}.swagger-ui .pb2-ns{padding-bottom:.5rem}.swagger-ui .pb3-ns{padding-bottom:1rem}.swagger-ui .pb4-ns{padding-bottom:2rem}.swagger-ui .pb5-ns{padding-bottom:4rem}.swagger-ui .pb6-ns{padding-bottom:8rem}.swagger-ui .pb7-ns{padding-bottom:16rem}.swagger-ui .pt0-ns{padding-top:0}.swagger-ui .pt1-ns{padding-top:.25rem}.swagger-ui .pt2-ns{padding-top:.5rem}.swagger-ui .pt3-ns{padding-top:1rem}.swagger-ui .pt4-ns{padding-top:2rem}.swagger-ui .pt5-ns{padding-top:4rem}.swagger-ui .pt6-ns{padding-top:8rem}.swagger-ui .pt7-ns{padding-top:16rem}.swagger-ui .pv0-ns{padding-bottom:0;padding-top:0}.swagger-ui .pv1-ns{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-ns{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-ns{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-ns{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-ns{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-ns{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-ns{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-ns{padding-left:0;padding-right:0}.swagger-ui .ph1-ns{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-ns{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-ns{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-ns{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-ns{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-ns{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-ns{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-ns{margin:0}.swagger-ui .ma1-ns{margin:.25rem}.swagger-ui .ma2-ns{margin:.5rem}.swagger-ui .ma3-ns{margin:1rem}.swagger-ui .ma4-ns{margin:2rem}.swagger-ui .ma5-ns{margin:4rem}.swagger-ui .ma6-ns{margin:8rem}.swagger-ui .ma7-ns{margin:16rem}.swagger-ui .ml0-ns{margin-left:0}.swagger-ui .ml1-ns{margin-left:.25rem}.swagger-ui .ml2-ns{margin-left:.5rem}.swagger-ui .ml3-ns{margin-left:1rem}.swagger-ui .ml4-ns{margin-left:2rem}.swagger-ui .ml5-ns{margin-left:4rem}.swagger-ui .ml6-ns{margin-left:8rem}.swagger-ui .ml7-ns{margin-left:16rem}.swagger-ui .mr0-ns{margin-right:0}.swagger-ui .mr1-ns{margin-right:.25rem}.swagger-ui .mr2-ns{margin-right:.5rem}.swagger-ui .mr3-ns{margin-right:1rem}.swagger-ui .mr4-ns{margin-right:2rem}.swagger-ui .mr5-ns{margin-right:4rem}.swagger-ui .mr6-ns{margin-right:8rem}.swagger-ui .mr7-ns{margin-right:16rem}.swagger-ui .mb0-ns{margin-bottom:0}.swagger-ui .mb1-ns{margin-bottom:.25rem}.swagger-ui .mb2-ns{margin-bottom:.5rem}.swagger-ui .mb3-ns{margin-bottom:1rem}.swagger-ui .mb4-ns{margin-bottom:2rem}.swagger-ui .mb5-ns{margin-bottom:4rem}.swagger-ui .mb6-ns{margin-bottom:8rem}.swagger-ui .mb7-ns{margin-bottom:16rem}.swagger-ui .mt0-ns{margin-top:0}.swagger-ui .mt1-ns{margin-top:.25rem}.swagger-ui .mt2-ns{margin-top:.5rem}.swagger-ui .mt3-ns{margin-top:1rem}.swagger-ui .mt4-ns{margin-top:2rem}.swagger-ui .mt5-ns{margin-top:4rem}.swagger-ui .mt6-ns{margin-top:8rem}.swagger-ui .mt7-ns{margin-top:16rem}.swagger-ui .mv0-ns{margin-bottom:0;margin-top:0}.swagger-ui .mv1-ns{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-ns{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-ns{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-ns{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-ns{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-ns{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-ns{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-ns{margin-left:0;margin-right:0}.swagger-ui .mh1-ns{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-ns{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-ns{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-ns{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-ns{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-ns{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-ns{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .pa0-m{padding:0}.swagger-ui .pa1-m{padding:.25rem}.swagger-ui .pa2-m{padding:.5rem}.swagger-ui .pa3-m{padding:1rem}.swagger-ui .pa4-m{padding:2rem}.swagger-ui .pa5-m{padding:4rem}.swagger-ui .pa6-m{padding:8rem}.swagger-ui .pa7-m{padding:16rem}.swagger-ui .pl0-m{padding-left:0}.swagger-ui .pl1-m{padding-left:.25rem}.swagger-ui .pl2-m{padding-left:.5rem}.swagger-ui .pl3-m{padding-left:1rem}.swagger-ui .pl4-m{padding-left:2rem}.swagger-ui .pl5-m{padding-left:4rem}.swagger-ui .pl6-m{padding-left:8rem}.swagger-ui .pl7-m{padding-left:16rem}.swagger-ui .pr0-m{padding-right:0}.swagger-ui .pr1-m{padding-right:.25rem}.swagger-ui .pr2-m{padding-right:.5rem}.swagger-ui .pr3-m{padding-right:1rem}.swagger-ui .pr4-m{padding-right:2rem}.swagger-ui .pr5-m{padding-right:4rem}.swagger-ui .pr6-m{padding-right:8rem}.swagger-ui .pr7-m{padding-right:16rem}.swagger-ui .pb0-m{padding-bottom:0}.swagger-ui .pb1-m{padding-bottom:.25rem}.swagger-ui .pb2-m{padding-bottom:.5rem}.swagger-ui .pb3-m{padding-bottom:1rem}.swagger-ui .pb4-m{padding-bottom:2rem}.swagger-ui .pb5-m{padding-bottom:4rem}.swagger-ui .pb6-m{padding-bottom:8rem}.swagger-ui .pb7-m{padding-bottom:16rem}.swagger-ui .pt0-m{padding-top:0}.swagger-ui .pt1-m{padding-top:.25rem}.swagger-ui .pt2-m{padding-top:.5rem}.swagger-ui .pt3-m{padding-top:1rem}.swagger-ui .pt4-m{padding-top:2rem}.swagger-ui .pt5-m{padding-top:4rem}.swagger-ui .pt6-m{padding-top:8rem}.swagger-ui .pt7-m{padding-top:16rem}.swagger-ui .pv0-m{padding-bottom:0;padding-top:0}.swagger-ui .pv1-m{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-m{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-m{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-m{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-m{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-m{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-m{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-m{padding-left:0;padding-right:0}.swagger-ui .ph1-m{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-m{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-m{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-m{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-m{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-m{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-m{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-m{margin:0}.swagger-ui .ma1-m{margin:.25rem}.swagger-ui .ma2-m{margin:.5rem}.swagger-ui .ma3-m{margin:1rem}.swagger-ui .ma4-m{margin:2rem}.swagger-ui .ma5-m{margin:4rem}.swagger-ui .ma6-m{margin:8rem}.swagger-ui .ma7-m{margin:16rem}.swagger-ui .ml0-m{margin-left:0}.swagger-ui .ml1-m{margin-left:.25rem}.swagger-ui .ml2-m{margin-left:.5rem}.swagger-ui .ml3-m{margin-left:1rem}.swagger-ui .ml4-m{margin-left:2rem}.swagger-ui .ml5-m{margin-left:4rem}.swagger-ui .ml6-m{margin-left:8rem}.swagger-ui .ml7-m{margin-left:16rem}.swagger-ui .mr0-m{margin-right:0}.swagger-ui .mr1-m{margin-right:.25rem}.swagger-ui .mr2-m{margin-right:.5rem}.swagger-ui .mr3-m{margin-right:1rem}.swagger-ui .mr4-m{margin-right:2rem}.swagger-ui .mr5-m{margin-right:4rem}.swagger-ui .mr6-m{margin-right:8rem}.swagger-ui .mr7-m{margin-right:16rem}.swagger-ui .mb0-m{margin-bottom:0}.swagger-ui .mb1-m{margin-bottom:.25rem}.swagger-ui .mb2-m{margin-bottom:.5rem}.swagger-ui .mb3-m{margin-bottom:1rem}.swagger-ui .mb4-m{margin-bottom:2rem}.swagger-ui .mb5-m{margin-bottom:4rem}.swagger-ui .mb6-m{margin-bottom:8rem}.swagger-ui .mb7-m{margin-bottom:16rem}.swagger-ui .mt0-m{margin-top:0}.swagger-ui .mt1-m{margin-top:.25rem}.swagger-ui .mt2-m{margin-top:.5rem}.swagger-ui .mt3-m{margin-top:1rem}.swagger-ui .mt4-m{margin-top:2rem}.swagger-ui .mt5-m{margin-top:4rem}.swagger-ui .mt6-m{margin-top:8rem}.swagger-ui .mt7-m{margin-top:16rem}.swagger-ui .mv0-m{margin-bottom:0;margin-top:0}.swagger-ui .mv1-m{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-m{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-m{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-m{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-m{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-m{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-m{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-m{margin-left:0;margin-right:0}.swagger-ui .mh1-m{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-m{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-m{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-m{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-m{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-m{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-m{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:60em){.swagger-ui .pa0-l{padding:0}.swagger-ui .pa1-l{padding:.25rem}.swagger-ui .pa2-l{padding:.5rem}.swagger-ui .pa3-l{padding:1rem}.swagger-ui .pa4-l{padding:2rem}.swagger-ui .pa5-l{padding:4rem}.swagger-ui .pa6-l{padding:8rem}.swagger-ui .pa7-l{padding:16rem}.swagger-ui .pl0-l{padding-left:0}.swagger-ui .pl1-l{padding-left:.25rem}.swagger-ui .pl2-l{padding-left:.5rem}.swagger-ui .pl3-l{padding-left:1rem}.swagger-ui .pl4-l{padding-left:2rem}.swagger-ui .pl5-l{padding-left:4rem}.swagger-ui .pl6-l{padding-left:8rem}.swagger-ui .pl7-l{padding-left:16rem}.swagger-ui .pr0-l{padding-right:0}.swagger-ui .pr1-l{padding-right:.25rem}.swagger-ui .pr2-l{padding-right:.5rem}.swagger-ui .pr3-l{padding-right:1rem}.swagger-ui .pr4-l{padding-right:2rem}.swagger-ui .pr5-l{padding-right:4rem}.swagger-ui .pr6-l{padding-right:8rem}.swagger-ui .pr7-l{padding-right:16rem}.swagger-ui .pb0-l{padding-bottom:0}.swagger-ui .pb1-l{padding-bottom:.25rem}.swagger-ui .pb2-l{padding-bottom:.5rem}.swagger-ui .pb3-l{padding-bottom:1rem}.swagger-ui .pb4-l{padding-bottom:2rem}.swagger-ui .pb5-l{padding-bottom:4rem}.swagger-ui .pb6-l{padding-bottom:8rem}.swagger-ui .pb7-l{padding-bottom:16rem}.swagger-ui .pt0-l{padding-top:0}.swagger-ui .pt1-l{padding-top:.25rem}.swagger-ui .pt2-l{padding-top:.5rem}.swagger-ui .pt3-l{padding-top:1rem}.swagger-ui .pt4-l{padding-top:2rem}.swagger-ui .pt5-l{padding-top:4rem}.swagger-ui .pt6-l{padding-top:8rem}.swagger-ui .pt7-l{padding-top:16rem}.swagger-ui .pv0-l{padding-bottom:0;padding-top:0}.swagger-ui .pv1-l{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-l{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-l{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-l{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-l{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-l{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-l{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-l{padding-left:0;padding-right:0}.swagger-ui .ph1-l{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-l{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-l{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-l{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-l{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-l{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-l{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-l{margin:0}.swagger-ui .ma1-l{margin:.25rem}.swagger-ui .ma2-l{margin:.5rem}.swagger-ui .ma3-l{margin:1rem}.swagger-ui .ma4-l{margin:2rem}.swagger-ui .ma5-l{margin:4rem}.swagger-ui .ma6-l{margin:8rem}.swagger-ui .ma7-l{margin:16rem}.swagger-ui .ml0-l{margin-left:0}.swagger-ui .ml1-l{margin-left:.25rem}.swagger-ui .ml2-l{margin-left:.5rem}.swagger-ui .ml3-l{margin-left:1rem}.swagger-ui .ml4-l{margin-left:2rem}.swagger-ui .ml5-l{margin-left:4rem}.swagger-ui .ml6-l{margin-left:8rem}.swagger-ui .ml7-l{margin-left:16rem}.swagger-ui .mr0-l{margin-right:0}.swagger-ui .mr1-l{margin-right:.25rem}.swagger-ui .mr2-l{margin-right:.5rem}.swagger-ui .mr3-l{margin-right:1rem}.swagger-ui .mr4-l{margin-right:2rem}.swagger-ui .mr5-l{margin-right:4rem}.swagger-ui .mr6-l{margin-right:8rem}.swagger-ui .mr7-l{margin-right:16rem}.swagger-ui .mb0-l{margin-bottom:0}.swagger-ui .mb1-l{margin-bottom:.25rem}.swagger-ui .mb2-l{margin-bottom:.5rem}.swagger-ui .mb3-l{margin-bottom:1rem}.swagger-ui .mb4-l{margin-bottom:2rem}.swagger-ui .mb5-l{margin-bottom:4rem}.swagger-ui .mb6-l{margin-bottom:8rem}.swagger-ui .mb7-l{margin-bottom:16rem}.swagger-ui .mt0-l{margin-top:0}.swagger-ui .mt1-l{margin-top:.25rem}.swagger-ui .mt2-l{margin-top:.5rem}.swagger-ui .mt3-l{margin-top:1rem}.swagger-ui .mt4-l{margin-top:2rem}.swagger-ui .mt5-l{margin-top:4rem}.swagger-ui .mt6-l{margin-top:8rem}.swagger-ui .mt7-l{margin-top:16rem}.swagger-ui .mv0-l{margin-bottom:0;margin-top:0}.swagger-ui .mv1-l{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-l{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-l{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-l{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-l{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-l{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-l{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-l{margin-left:0;margin-right:0}.swagger-ui .mh1-l{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-l{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-l{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-l{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-l{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-l{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-l{margin-left:16rem;margin-right:16rem}}.swagger-ui .na1{margin:-.25rem}.swagger-ui .na2{margin:-.5rem}.swagger-ui .na3{margin:-1rem}.swagger-ui .na4{margin:-2rem}.swagger-ui .na5{margin:-4rem}.swagger-ui .na6{margin:-8rem}.swagger-ui .na7{margin:-16rem}.swagger-ui .nl1{margin-left:-.25rem}.swagger-ui .nl2{margin-left:-.5rem}.swagger-ui .nl3{margin-left:-1rem}.swagger-ui .nl4{margin-left:-2rem}.swagger-ui .nl5{margin-left:-4rem}.swagger-ui .nl6{margin-left:-8rem}.swagger-ui .nl7{margin-left:-16rem}.swagger-ui .nr1{margin-right:-.25rem}.swagger-ui .nr2{margin-right:-.5rem}.swagger-ui .nr3{margin-right:-1rem}.swagger-ui .nr4{margin-right:-2rem}.swagger-ui .nr5{margin-right:-4rem}.swagger-ui .nr6{margin-right:-8rem}.swagger-ui .nr7{margin-right:-16rem}.swagger-ui .nb1{margin-bottom:-.25rem}.swagger-ui .nb2{margin-bottom:-.5rem}.swagger-ui .nb3{margin-bottom:-1rem}.swagger-ui .nb4{margin-bottom:-2rem}.swagger-ui .nb5{margin-bottom:-4rem}.swagger-ui .nb6{margin-bottom:-8rem}.swagger-ui .nb7{margin-bottom:-16rem}.swagger-ui .nt1{margin-top:-.25rem}.swagger-ui .nt2{margin-top:-.5rem}.swagger-ui .nt3{margin-top:-1rem}.swagger-ui .nt4{margin-top:-2rem}.swagger-ui .nt5{margin-top:-4rem}.swagger-ui .nt6{margin-top:-8rem}.swagger-ui .nt7{margin-top:-16rem}@media screen and (min-width:30em){.swagger-ui .na1-ns{margin:-.25rem}.swagger-ui .na2-ns{margin:-.5rem}.swagger-ui .na3-ns{margin:-1rem}.swagger-ui .na4-ns{margin:-2rem}.swagger-ui .na5-ns{margin:-4rem}.swagger-ui .na6-ns{margin:-8rem}.swagger-ui .na7-ns{margin:-16rem}.swagger-ui .nl1-ns{margin-left:-.25rem}.swagger-ui .nl2-ns{margin-left:-.5rem}.swagger-ui .nl3-ns{margin-left:-1rem}.swagger-ui .nl4-ns{margin-left:-2rem}.swagger-ui .nl5-ns{margin-left:-4rem}.swagger-ui .nl6-ns{margin-left:-8rem}.swagger-ui .nl7-ns{margin-left:-16rem}.swagger-ui .nr1-ns{margin-right:-.25rem}.swagger-ui .nr2-ns{margin-right:-.5rem}.swagger-ui .nr3-ns{margin-right:-1rem}.swagger-ui .nr4-ns{margin-right:-2rem}.swagger-ui .nr5-ns{margin-right:-4rem}.swagger-ui .nr6-ns{margin-right:-8rem}.swagger-ui .nr7-ns{margin-right:-16rem}.swagger-ui .nb1-ns{margin-bottom:-.25rem}.swagger-ui .nb2-ns{margin-bottom:-.5rem}.swagger-ui .nb3-ns{margin-bottom:-1rem}.swagger-ui .nb4-ns{margin-bottom:-2rem}.swagger-ui .nb5-ns{margin-bottom:-4rem}.swagger-ui .nb6-ns{margin-bottom:-8rem}.swagger-ui .nb7-ns{margin-bottom:-16rem}.swagger-ui .nt1-ns{margin-top:-.25rem}.swagger-ui .nt2-ns{margin-top:-.5rem}.swagger-ui .nt3-ns{margin-top:-1rem}.swagger-ui .nt4-ns{margin-top:-2rem}.swagger-ui .nt5-ns{margin-top:-4rem}.swagger-ui .nt6-ns{margin-top:-8rem}.swagger-ui .nt7-ns{margin-top:-16rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .na1-m{margin:-.25rem}.swagger-ui .na2-m{margin:-.5rem}.swagger-ui .na3-m{margin:-1rem}.swagger-ui .na4-m{margin:-2rem}.swagger-ui .na5-m{margin:-4rem}.swagger-ui .na6-m{margin:-8rem}.swagger-ui .na7-m{margin:-16rem}.swagger-ui .nl1-m{margin-left:-.25rem}.swagger-ui .nl2-m{margin-left:-.5rem}.swagger-ui .nl3-m{margin-left:-1rem}.swagger-ui .nl4-m{margin-left:-2rem}.swagger-ui .nl5-m{margin-left:-4rem}.swagger-ui .nl6-m{margin-left:-8rem}.swagger-ui .nl7-m{margin-left:-16rem}.swagger-ui .nr1-m{margin-right:-.25rem}.swagger-ui .nr2-m{margin-right:-.5rem}.swagger-ui .nr3-m{margin-right:-1rem}.swagger-ui .nr4-m{margin-right:-2rem}.swagger-ui .nr5-m{margin-right:-4rem}.swagger-ui .nr6-m{margin-right:-8rem}.swagger-ui .nr7-m{margin-right:-16rem}.swagger-ui .nb1-m{margin-bottom:-.25rem}.swagger-ui .nb2-m{margin-bottom:-.5rem}.swagger-ui .nb3-m{margin-bottom:-1rem}.swagger-ui .nb4-m{margin-bottom:-2rem}.swagger-ui .nb5-m{margin-bottom:-4rem}.swagger-ui .nb6-m{margin-bottom:-8rem}.swagger-ui .nb7-m{margin-bottom:-16rem}.swagger-ui .nt1-m{margin-top:-.25rem}.swagger-ui .nt2-m{margin-top:-.5rem}.swagger-ui .nt3-m{margin-top:-1rem}.swagger-ui .nt4-m{margin-top:-2rem}.swagger-ui .nt5-m{margin-top:-4rem}.swagger-ui .nt6-m{margin-top:-8rem}.swagger-ui .nt7-m{margin-top:-16rem}}@media screen and (min-width:60em){.swagger-ui .na1-l{margin:-.25rem}.swagger-ui .na2-l{margin:-.5rem}.swagger-ui .na3-l{margin:-1rem}.swagger-ui .na4-l{margin:-2rem}.swagger-ui .na5-l{margin:-4rem}.swagger-ui .na6-l{margin:-8rem}.swagger-ui .na7-l{margin:-16rem}.swagger-ui .nl1-l{margin-left:-.25rem}.swagger-ui .nl2-l{margin-left:-.5rem}.swagger-ui .nl3-l{margin-left:-1rem}.swagger-ui .nl4-l{margin-left:-2rem}.swagger-ui .nl5-l{margin-left:-4rem}.swagger-ui .nl6-l{margin-left:-8rem}.swagger-ui .nl7-l{margin-left:-16rem}.swagger-ui .nr1-l{margin-right:-.25rem}.swagger-ui .nr2-l{margin-right:-.5rem}.swagger-ui .nr3-l{margin-right:-1rem}.swagger-ui .nr4-l{margin-right:-2rem}.swagger-ui .nr5-l{margin-right:-4rem}.swagger-ui .nr6-l{margin-right:-8rem}.swagger-ui .nr7-l{margin-right:-16rem}.swagger-ui .nb1-l{margin-bottom:-.25rem}.swagger-ui .nb2-l{margin-bottom:-.5rem}.swagger-ui .nb3-l{margin-bottom:-1rem}.swagger-ui .nb4-l{margin-bottom:-2rem}.swagger-ui .nb5-l{margin-bottom:-4rem}.swagger-ui .nb6-l{margin-bottom:-8rem}.swagger-ui .nb7-l{margin-bottom:-16rem}.swagger-ui .nt1-l{margin-top:-.25rem}.swagger-ui .nt2-l{margin-top:-.5rem}.swagger-ui .nt3-l{margin-top:-1rem}.swagger-ui .nt4-l{margin-top:-2rem}.swagger-ui .nt5-l{margin-top:-4rem}.swagger-ui .nt6-l{margin-top:-8rem}.swagger-ui .nt7-l{margin-top:-16rem}}.swagger-ui .collapse{border-collapse:collapse;border-spacing:0}.swagger-ui .striped--light-silver:nth-child(odd){background-color:#aaa}.swagger-ui .striped--moon-gray:nth-child(odd){background-color:#ccc}.swagger-ui .striped--light-gray:nth-child(odd){background-color:#eee}.swagger-ui .striped--near-white:nth-child(odd){background-color:#f4f4f4}.swagger-ui .stripe-light:nth-child(odd){background-color:hsla(0,0%,100%,.1)}.swagger-ui .stripe-dark:nth-child(odd){background-color:rgba(0,0,0,.1)}.swagger-ui .strike{text-decoration:line-through}.swagger-ui .underline{text-decoration:underline}.swagger-ui .no-underline{text-decoration:none}@media screen and (min-width:30em){.swagger-ui .strike-ns{text-decoration:line-through}.swagger-ui .underline-ns{text-decoration:underline}.swagger-ui .no-underline-ns{text-decoration:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .strike-m{text-decoration:line-through}.swagger-ui .underline-m{text-decoration:underline}.swagger-ui .no-underline-m{text-decoration:none}}@media screen and (min-width:60em){.swagger-ui .strike-l{text-decoration:line-through}.swagger-ui .underline-l{text-decoration:underline}.swagger-ui .no-underline-l{text-decoration:none}}.swagger-ui .tl{text-align:left}.swagger-ui .tr{text-align:right}.swagger-ui .tc{text-align:center}.swagger-ui .tj{text-align:justify}@media screen and (min-width:30em){.swagger-ui .tl-ns{text-align:left}.swagger-ui .tr-ns{text-align:right}.swagger-ui .tc-ns{text-align:center}.swagger-ui .tj-ns{text-align:justify}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .tl-m{text-align:left}.swagger-ui .tr-m{text-align:right}.swagger-ui .tc-m{text-align:center}.swagger-ui .tj-m{text-align:justify}}@media screen and (min-width:60em){.swagger-ui .tl-l{text-align:left}.swagger-ui .tr-l{text-align:right}.swagger-ui .tc-l{text-align:center}.swagger-ui .tj-l{text-align:justify}}.swagger-ui .ttc{text-transform:capitalize}.swagger-ui .ttl{text-transform:lowercase}.swagger-ui .ttu{text-transform:uppercase}.swagger-ui .ttn{text-transform:none}@media screen and (min-width:30em){.swagger-ui .ttc-ns{text-transform:capitalize}.swagger-ui .ttl-ns{text-transform:lowercase}.swagger-ui .ttu-ns{text-transform:uppercase}.swagger-ui .ttn-ns{text-transform:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ttc-m{text-transform:capitalize}.swagger-ui .ttl-m{text-transform:lowercase}.swagger-ui .ttu-m{text-transform:uppercase}.swagger-ui .ttn-m{text-transform:none}}@media screen and (min-width:60em){.swagger-ui .ttc-l{text-transform:capitalize}.swagger-ui .ttl-l{text-transform:lowercase}.swagger-ui .ttu-l{text-transform:uppercase}.swagger-ui .ttn-l{text-transform:none}}.swagger-ui .f-6,.swagger-ui .f-headline{font-size:6rem}.swagger-ui .f-5,.swagger-ui .f-subheadline{font-size:5rem}.swagger-ui .f1{font-size:3rem}.swagger-ui .f2{font-size:2.25rem}.swagger-ui .f3{font-size:1.5rem}.swagger-ui .f4{font-size:1.25rem}.swagger-ui .f5{font-size:1rem}.swagger-ui .f6{font-size:.875rem}.swagger-ui .f7{font-size:.75rem}@media screen and (min-width:30em){.swagger-ui .f-6-ns,.swagger-ui .f-headline-ns{font-size:6rem}.swagger-ui .f-5-ns,.swagger-ui .f-subheadline-ns{font-size:5rem}.swagger-ui .f1-ns{font-size:3rem}.swagger-ui .f2-ns{font-size:2.25rem}.swagger-ui .f3-ns{font-size:1.5rem}.swagger-ui .f4-ns{font-size:1.25rem}.swagger-ui .f5-ns{font-size:1rem}.swagger-ui .f6-ns{font-size:.875rem}.swagger-ui .f7-ns{font-size:.75rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .f-6-m,.swagger-ui .f-headline-m{font-size:6rem}.swagger-ui .f-5-m,.swagger-ui .f-subheadline-m{font-size:5rem}.swagger-ui .f1-m{font-size:3rem}.swagger-ui .f2-m{font-size:2.25rem}.swagger-ui .f3-m{font-size:1.5rem}.swagger-ui .f4-m{font-size:1.25rem}.swagger-ui .f5-m{font-size:1rem}.swagger-ui .f6-m{font-size:.875rem}.swagger-ui .f7-m{font-size:.75rem}}@media screen and (min-width:60em){.swagger-ui .f-6-l,.swagger-ui .f-headline-l{font-size:6rem}.swagger-ui .f-5-l,.swagger-ui .f-subheadline-l{font-size:5rem}.swagger-ui .f1-l{font-size:3rem}.swagger-ui .f2-l{font-size:2.25rem}.swagger-ui .f3-l{font-size:1.5rem}.swagger-ui .f4-l{font-size:1.25rem}.swagger-ui .f5-l{font-size:1rem}.swagger-ui .f6-l{font-size:.875rem}.swagger-ui .f7-l{font-size:.75rem}}.swagger-ui .measure{max-width:30em}.swagger-ui .measure-wide{max-width:34em}.swagger-ui .measure-narrow{max-width:20em}.swagger-ui .indent{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media screen and (min-width:30em){.swagger-ui .measure-ns{max-width:30em}.swagger-ui .measure-wide-ns{max-width:34em}.swagger-ui .measure-narrow-ns{max-width:20em}.swagger-ui .indent-ns{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-ns{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-ns{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .measure-m{max-width:30em}.swagger-ui .measure-wide-m{max-width:34em}.swagger-ui .measure-narrow-m{max-width:20em}.swagger-ui .indent-m{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-m{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-m{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}@media screen and (min-width:60em){.swagger-ui .measure-l{max-width:30em}.swagger-ui .measure-wide-l{max-width:34em}.swagger-ui .measure-narrow-l{max-width:20em}.swagger-ui .indent-l{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-l{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-l{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}.swagger-ui .overflow-container{overflow-y:scroll}.swagger-ui .center{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto{margin-right:auto}.swagger-ui .ml-auto{margin-left:auto}@media screen and (min-width:30em){.swagger-ui .center-ns{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-ns{margin-right:auto}.swagger-ui .ml-auto-ns{margin-left:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .center-m{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-m{margin-right:auto}.swagger-ui .ml-auto-m{margin-left:auto}}@media screen and (min-width:60em){.swagger-ui .center-l{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-l{margin-right:auto}.swagger-ui .ml-auto-l{margin-left:auto}}.swagger-ui .clip{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);position:fixed!important;_position:absolute!important}@media screen and (min-width:30em){.swagger-ui .clip-ns{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);position:fixed!important;_position:absolute!important}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .clip-m{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);position:fixed!important;_position:absolute!important}}@media screen and (min-width:60em){.swagger-ui .clip-l{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);position:fixed!important;_position:absolute!important}}.swagger-ui .ws-normal{white-space:normal}.swagger-ui .nowrap{white-space:nowrap}.swagger-ui .pre{white-space:pre}@media screen and (min-width:30em){.swagger-ui .ws-normal-ns{white-space:normal}.swagger-ui .nowrap-ns{white-space:nowrap}.swagger-ui .pre-ns{white-space:pre}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ws-normal-m{white-space:normal}.swagger-ui .nowrap-m{white-space:nowrap}.swagger-ui .pre-m{white-space:pre}}@media screen and (min-width:60em){.swagger-ui .ws-normal-l{white-space:normal}.swagger-ui .nowrap-l{white-space:nowrap}.swagger-ui .pre-l{white-space:pre}}.swagger-ui .v-base{vertical-align:baseline}.swagger-ui .v-mid{vertical-align:middle}.swagger-ui .v-top{vertical-align:top}.swagger-ui .v-btm{vertical-align:bottom}@media screen and (min-width:30em){.swagger-ui .v-base-ns{vertical-align:baseline}.swagger-ui .v-mid-ns{vertical-align:middle}.swagger-ui .v-top-ns{vertical-align:top}.swagger-ui .v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .v-base-m{vertical-align:baseline}.swagger-ui .v-mid-m{vertical-align:middle}.swagger-ui .v-top-m{vertical-align:top}.swagger-ui .v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.swagger-ui .v-base-l{vertical-align:baseline}.swagger-ui .v-mid-l{vertical-align:middle}.swagger-ui .v-top-l{vertical-align:top}.swagger-ui .v-btm-l{vertical-align:bottom}}.swagger-ui .dim{opacity:1;transition:opacity .15s ease-in}.swagger-ui .dim:focus,.swagger-ui .dim:hover{opacity:.5;transition:opacity .15s ease-in}.swagger-ui .dim:active{opacity:.8;transition:opacity .15s ease-out}.swagger-ui .glow{transition:opacity .15s ease-in}.swagger-ui .glow:focus,.swagger-ui .glow:hover{opacity:1;transition:opacity .15s ease-in}.swagger-ui .hide-child .child{opacity:0;transition:opacity .15s ease-in}.swagger-ui .hide-child:active .child,.swagger-ui .hide-child:focus .child,.swagger-ui .hide-child:hover .child{opacity:1;transition:opacity .15s ease-in}.swagger-ui .underline-hover:focus,.swagger-ui .underline-hover:hover{text-decoration:underline}.swagger-ui .grow{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;transform:translateZ(0);transition:transform .25s ease-out}.swagger-ui .grow:focus,.swagger-ui .grow:hover{transform:scale(1.05)}.swagger-ui .grow:active{transform:scale(.9)}.swagger-ui .grow-large{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;transform:translateZ(0);transition:transform .25s ease-in-out}.swagger-ui .grow-large:focus,.swagger-ui .grow-large:hover{transform:scale(1.2)}.swagger-ui .grow-large:active{transform:scale(.95)}.swagger-ui .pointer:hover{cursor:pointer}.swagger-ui .shadow-hover{cursor:pointer;position:relative;transition:all .5s cubic-bezier(.165,.84,.44,1)}.swagger-ui .shadow-hover:after{border-radius:inherit;box-shadow:0 0 16px 2px rgba(0,0,0,.2);content:"";height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .5s cubic-bezier(.165,.84,.44,1);width:100%;z-index:-1}.swagger-ui .shadow-hover:focus:after,.swagger-ui .shadow-hover:hover:after{opacity:1}.swagger-ui .bg-animate,.swagger-ui .bg-animate:focus,.swagger-ui .bg-animate:hover{transition:background-color .15s ease-in-out}.swagger-ui .z-0{z-index:0}.swagger-ui .z-1{z-index:1}.swagger-ui .z-2{z-index:2}.swagger-ui .z-3{z-index:3}.swagger-ui .z-4{z-index:4}.swagger-ui .z-5{z-index:5}.swagger-ui .z-999{z-index:999}.swagger-ui .z-9999{z-index:9999}.swagger-ui .z-max{z-index:2147483647}.swagger-ui .z-inherit{z-index:inherit}.swagger-ui .z-initial{z-index:auto}.swagger-ui .z-unset{z-index:unset}.swagger-ui .nested-copy-line-height ol,.swagger-ui .nested-copy-line-height p,.swagger-ui .nested-copy-line-height ul{line-height:1.5}.swagger-ui .nested-headline-line-height h1,.swagger-ui .nested-headline-line-height h2,.swagger-ui .nested-headline-line-height h3,.swagger-ui .nested-headline-line-height h4,.swagger-ui .nested-headline-line-height h5,.swagger-ui .nested-headline-line-height h6{line-height:1.25}.swagger-ui .nested-list-reset ol,.swagger-ui .nested-list-reset ul{list-style-type:none;margin-left:0;padding-left:0}.swagger-ui .nested-copy-indent p+p{margin-bottom:0;margin-top:0;text-indent:.1em}.swagger-ui .nested-copy-seperator p+p{margin-top:1.5em}.swagger-ui .nested-img img{display:block;max-width:100%;width:100%}.swagger-ui .nested-links a{color:#357edd;transition:color .15s ease-in}.swagger-ui .nested-links a:focus,.swagger-ui .nested-links a:hover{color:#96ccff;transition:color .15s ease-in}.swagger-ui .wrapper{box-sizing:border-box;margin:0 auto;max-width:1460px;padding:0 20px;width:100%}.swagger-ui .opblock-tag-section{display:flex;flex-direction:column}.swagger-ui .try-out.btn-group{display:flex;flex:0.1 2 auto;padding:0}.swagger-ui .try-out__btn{margin-left:1.25rem}.swagger-ui .opblock-tag{align-items:center;border-bottom:1px solid rgba(59,65,81,.3);cursor:pointer;display:flex;padding:10px 20px 10px 10px;transition:all .2s}.swagger-ui .opblock-tag:hover{background:rgba(0,0,0,.02)}.swagger-ui .opblock-tag{color:#3b4151;font-family:sans-serif;font-size:24px;margin:0 0 5px}.swagger-ui .opblock-tag.no-desc span{flex:1}.swagger-ui .opblock-tag svg{transition:all .4s}.swagger-ui .opblock-tag small{color:#3b4151;flex:1;font-family:sans-serif;font-size:14px;font-weight:400;padding:0 10px}.swagger-ui .parameter__type{color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;padding:5px 0}.swagger-ui .parameter-controls{margin-top:.75em}.swagger-ui .examples__title{display:block;font-size:1.1em;font-weight:700;margin-bottom:.75em}.swagger-ui .examples__section{margin-top:1.5em}.swagger-ui .examples__section-header{font-size:.9rem;font-weight:700;margin-bottom:.5rem}.swagger-ui .examples-select{display:inline-block;margin-bottom:.75em}.swagger-ui .examples-select .examples-select-element{width:100%}.swagger-ui .examples-select__section-label{font-size:.9rem;font-weight:700;margin-right:.5rem}.swagger-ui .example__section{margin-top:1.5em}.swagger-ui .example__section-header{font-size:.9rem;font-weight:700;margin-bottom:.5rem}.swagger-ui .view-line-link{cursor:pointer;margin:0 5px;position:relative;top:3px;transition:all .5s;width:20px}.swagger-ui .opblock{border:1px solid #000;border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.19);margin:0 0 15px}.swagger-ui .opblock .tab-header{display:flex;flex:1}.swagger-ui .opblock .tab-header .tab-item{cursor:pointer;padding:0 40px}.swagger-ui .opblock .tab-header .tab-item:first-of-type{padding:0 40px 0 0}.swagger-ui .opblock .tab-header .tab-item.active h4 span{position:relative}.swagger-ui .opblock .tab-header .tab-item.active h4 span:after{background:gray;bottom:-15px;content:"";height:4px;left:50%;position:absolute;transform:translateX(-50%);width:120%}.swagger-ui .opblock.is-open .opblock-summary{border-bottom:1px solid #000}.swagger-ui .opblock .opblock-section-header{align-items:center;background:hsla(0,0%,100%,.8);box-shadow:0 1px 2px rgba(0,0,0,.1);display:flex;min-height:50px;padding:8px 20px}.swagger-ui .opblock .opblock-section-header>label{align-items:center;color:#3b4151;display:flex;font-family:sans-serif;font-size:12px;font-weight:700;margin:0 0 0 auto}.swagger-ui .opblock .opblock-section-header>label>span{padding:0 10px 0 0}.swagger-ui .opblock .opblock-section-header h4{color:#3b4151;flex:1;font-family:sans-serif;font-size:14px;margin:0}.swagger-ui .opblock .opblock-summary-method{background:#000;border-radius:3px;color:#fff;font-family:sans-serif;font-size:14px;font-weight:700;min-width:80px;padding:6px 0;text-align:center;text-shadow:0 1px 0 rgba(0,0,0,.1)}.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{align-items:center;color:#3b4151;display:flex;font-family:monospace;font-size:16px;font-weight:600;padding:0 10px;word-break:break-word}@media (max-width:768px){.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{font-size:12px}}.swagger-ui .opblock .opblock-summary-path{flex-shrink:0;max-width:calc(100% - 110px - 15rem)}.swagger-ui .opblock .opblock-summary-path__deprecated{text-decoration:line-through}.swagger-ui .opblock .opblock-summary-operation-id{font-size:14px}.swagger-ui .opblock .opblock-summary-description{color:#3b4151;flex:1 1 auto;font-family:sans-serif;font-size:13px;word-break:break-word}.swagger-ui .opblock .opblock-summary{align-items:center;cursor:pointer;display:flex;padding:5px}.swagger-ui .opblock .opblock-summary .view-line-link{cursor:pointer;margin:0;position:relative;top:2px;transition:all .5s;width:0}.swagger-ui .opblock .opblock-summary:hover .view-line-link{margin:0 5px;width:18px}.swagger-ui .opblock.opblock-post{background:rgba(73,204,144,.1);border-color:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary-method{background:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary{border-color:#49cc90}.swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span:after{background:#49cc90}.swagger-ui .opblock.opblock-put{background:rgba(252,161,48,.1);border-color:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary-method{background:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary{border-color:#fca130}.swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span:after{background:#fca130}.swagger-ui .opblock.opblock-delete{background:rgba(249,62,62,.1);border-color:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary-method{background:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary{border-color:#f93e3e}.swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span:after{background:#f93e3e}.swagger-ui .opblock.opblock-get{background:rgba(97,175,254,.1);border-color:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary-method{background:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary{border-color:#61affe}.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span:after{background:#61affe}.swagger-ui .opblock.opblock-patch{background:rgba(80,227,194,.1);border-color:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary-method{background:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary{border-color:#50e3c2}.swagger-ui .opblock.opblock-patch .tab-header .tab-item.active h4 span:after{background:#50e3c2}.swagger-ui .opblock.opblock-head{background:rgba(144,18,254,.1);border-color:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary-method{background:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary{border-color:#9012fe}.swagger-ui .opblock.opblock-head .tab-header .tab-item.active h4 span:after{background:#9012fe}.swagger-ui .opblock.opblock-options{background:rgba(13,90,167,.1);border-color:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary-method{background:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary{border-color:#0d5aa7}.swagger-ui .opblock.opblock-options .tab-header .tab-item.active h4 span:after{background:#0d5aa7}.swagger-ui .opblock.opblock-deprecated{background:hsla(0,0%,92%,.1);border-color:#ebebeb;opacity:.6}.swagger-ui .opblock.opblock-deprecated .opblock-summary-method{background:#ebebeb}.swagger-ui .opblock.opblock-deprecated .opblock-summary{border-color:#ebebeb}.swagger-ui .opblock.opblock-deprecated .tab-header .tab-item.active h4 span:after{background:#ebebeb}.swagger-ui .opblock .opblock-schemes{padding:8px 20px}.swagger-ui .opblock .opblock-schemes .schemes-title{padding:0 10px 0 0}.swagger-ui .filter .operation-filter-input{border:2px solid #d8dde7;margin:20px 0;padding:10px;width:100%}.swagger-ui .download-url-wrapper .failed,.swagger-ui .filter .failed{color:red}.swagger-ui .download-url-wrapper .loading,.swagger-ui .filter .loading{color:#aaa}.swagger-ui .model-example{margin-top:1em}.swagger-ui .tab{display:flex;list-style:none;padding:0}.swagger-ui .tab li{color:#3b4151;cursor:pointer;font-family:sans-serif;font-size:12px;min-width:60px;padding:0}.swagger-ui .tab li:first-of-type{padding-left:0;padding-right:12px;position:relative}.swagger-ui .tab li:first-of-type:after{background:rgba(0,0,0,.2);content:"";height:100%;position:absolute;right:6px;top:0;width:1px}.swagger-ui .tab li.active{font-weight:700}.swagger-ui .tab li button.tablinks{background:none;border:0;color:inherit;font-family:inherit;font-weight:inherit;padding:0}.swagger-ui .opblock-description-wrapper,.swagger-ui .opblock-external-docs-wrapper,.swagger-ui .opblock-title_normal{color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px;padding:15px 20px}.swagger-ui .opblock-description-wrapper h4,.swagger-ui .opblock-external-docs-wrapper h4,.swagger-ui .opblock-title_normal h4{color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px}.swagger-ui .opblock-description-wrapper p,.swagger-ui .opblock-external-docs-wrapper p,.swagger-ui .opblock-title_normal p{color:#3b4151;font-family:sans-serif;font-size:14px;margin:0}.swagger-ui .opblock-external-docs-wrapper h4{padding-left:0}.swagger-ui .execute-wrapper{padding:20px;text-align:right}.swagger-ui .execute-wrapper .btn{padding:8px 40px;width:100%}.swagger-ui .body-param-options{display:flex;flex-direction:column}.swagger-ui .body-param-options .body-param-edit{padding:10px 0}.swagger-ui .body-param-options label{padding:8px 0}.swagger-ui .body-param-options label select{margin:3px 0 0}.swagger-ui .responses-inner{padding:20px}.swagger-ui .responses-inner h4,.swagger-ui .responses-inner h5{color:#3b4151;font-family:sans-serif;font-size:12px;margin:10px 0 5px}.swagger-ui .responses-inner .curl{white-space:normal}.swagger-ui .response-col_status{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .response-col_status .response-undocumented{color:#909090;font-family:monospace;font-size:11px;font-weight:600}.swagger-ui .response-col_links{color:#3b4151;font-family:sans-serif;font-size:14px;max-width:40em;padding-left:2em}.swagger-ui .response-col_links .response-undocumented{color:#909090;font-family:monospace;font-size:11px;font-weight:600}.swagger-ui .response-col_links .operation-link{margin-bottom:1.5em}.swagger-ui .response-col_links .operation-link .description{margin-bottom:.5em}.swagger-ui .opblock-body .opblock-loading-animation{display:block;margin:3em auto}.swagger-ui .opblock-body pre.microlight{word-wrap:break-word;background:#333;border-radius:4px;color:#fff;font-family:monospace;font-size:12px;font-weight:600;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;margin:0;padding:10px;white-space:pre-wrap;word-break:break-all;word-break:break-word}.swagger-ui .opblock-body pre.microlight .headerline{display:block}.swagger-ui .highlight-code{position:relative}.swagger-ui .highlight-code>.microlight{max-height:400px;min-height:6em;overflow-y:auto}.swagger-ui .highlight-code>.microlight code{white-space:pre-wrap!important;word-break:break-all}.swagger-ui .curl-command{position:relative}.swagger-ui .download-contents{align-items:center;background:#7d8293;border-radius:4px;bottom:10px;color:#fff;cursor:pointer;display:flex;font-family:sans-serif;font-size:14px;font-weight:600;height:30px;justify-content:center;padding:5px;position:absolute;right:10px;text-align:center}.swagger-ui .scheme-container{background:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.15);margin:0 0 20px;padding:30px 0}.swagger-ui .scheme-container .schemes{align-items:flex-end;display:flex}.swagger-ui .scheme-container .schemes>label{color:#3b4151;display:flex;flex-direction:column;font-family:sans-serif;font-size:12px;font-weight:700;margin:-20px 15px 0 0}.swagger-ui .scheme-container .schemes>label select{min-width:130px;text-transform:uppercase}.swagger-ui .loading-container{align-items:center;display:flex;flex-direction:column;justify-content:center;margin-top:1em;min-height:1px;padding:40px 0 60px}.swagger-ui .loading-container .loading{position:relative}.swagger-ui .loading-container .loading:after{color:#3b4151;content:"loading";font-family:sans-serif;font-size:10px;font-weight:700;left:50%;position:absolute;text-transform:uppercase;top:50%;transform:translate(-50%,-50%)}.swagger-ui .loading-container .loading:before{-webkit-animation:rotation 1s linear infinite,opacity .5s;animation:rotation 1s linear infinite,opacity .5s;-webkit-backface-visibility:hidden;backface-visibility:hidden;border:2px solid rgba(85,85,85,.1);border-radius:100%;border-top-color:rgba(0,0,0,.6);content:"";display:block;height:60px;left:50%;margin:-30px;opacity:1;position:absolute;top:50%;width:60px}@-webkit-keyframes rotation{to{transform:rotate(1turn)}}@keyframes rotation{to{transform:rotate(1turn)}}.swagger-ui .response-controls{display:flex;padding-top:1em}.swagger-ui .response-control-media-type{margin-right:1em}.swagger-ui .response-control-media-type--accept-controller select{border-color:green}.swagger-ui .response-control-media-type__accept-message{color:green;font-size:.7em}.swagger-ui .response-control-examples__title,.swagger-ui .response-control-media-type__title{display:block;font-size:.7em;margin-bottom:.2em}@-webkit-keyframes blinker{50%{opacity:0}}@keyframes blinker{50%{opacity:0}}.swagger-ui .hidden{display:none}.swagger-ui .no-margin{border:none;height:auto;margin:0;padding:0}.swagger-ui .float-right{float:right}.swagger-ui .svg-assets{height:0;position:absolute;width:0}.swagger-ui section h3{color:#3b4151;font-family:sans-serif}.swagger-ui a.nostyle{display:inline}.swagger-ui a.nostyle,.swagger-ui a.nostyle:visited{color:inherit;cursor:pointer;text-decoration:inherit}.swagger-ui .fallback{color:#aaa;padding:1em}.swagger-ui .version-pragma{height:100%;padding:5em 0}.swagger-ui .version-pragma__message{display:flex;font-size:1.2em;height:100%;justify-content:center;line-height:1.5em;padding:0 .6em;text-align:center}.swagger-ui .version-pragma__message>div{flex:1;max-width:55ch}.swagger-ui .version-pragma__message code{background-color:#dedede;padding:4px 4px 2px;white-space:pre}.swagger-ui .opblock-link{font-weight:400}.swagger-ui .opblock-link.shown{font-weight:700}.swagger-ui span.token-string{color:#555}.swagger-ui span.token-not-formatted{color:#555;font-weight:700}.swagger-ui .btn{background:transparent;border:2px solid gray;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:#3b4151;font-family:sans-serif;font-size:14px;font-weight:700;padding:5px 23px;transition:all .3s}.swagger-ui .btn.btn-sm{font-size:12px;padding:4px 23px}.swagger-ui .btn[disabled]{cursor:not-allowed;opacity:.3}.swagger-ui .btn:hover{box-shadow:0 0 5px rgba(0,0,0,.3)}.swagger-ui .btn.cancel{background-color:transparent;border-color:#ff6060;color:#ff6060;font-family:sans-serif}.swagger-ui .btn.authorize{background-color:transparent;border-color:#49cc90;color:#49cc90;display:inline;line-height:1}.swagger-ui .btn.authorize span{float:left;padding:4px 20px 0 0}.swagger-ui .btn.authorize svg{fill:#49cc90}.swagger-ui .btn.execute{background-color:#4990e2;border-color:#4990e2;color:#fff}.swagger-ui .btn-group{display:flex;padding:30px}.swagger-ui .btn-group .btn{flex:1}.swagger-ui .btn-group .btn:first-child{border-radius:4px 0 0 4px}.swagger-ui .btn-group .btn:last-child{border-radius:0 4px 4px 0}.swagger-ui .authorization__btn{background:none;border:none;padding:0 10px}.swagger-ui .authorization__btn.locked{opacity:1}.swagger-ui .authorization__btn.unlocked{opacity:.4}.swagger-ui .model-box-control,.swagger-ui .models-control,.swagger-ui .opblock-summary-control{all:inherit;border-bottom:0;cursor:pointer;flex:1;padding:0}.swagger-ui .model-box-control:focus,.swagger-ui .models-control:focus,.swagger-ui .opblock-summary-control:focus{outline:auto}.swagger-ui .expand-methods,.swagger-ui .expand-operation{background:none;border:none}.swagger-ui .expand-methods svg,.swagger-ui .expand-operation svg{height:20px;width:20px}.swagger-ui .expand-methods{padding:0 10px}.swagger-ui .expand-methods:hover svg{fill:#404040}.swagger-ui .expand-methods svg{fill:#707070;transition:all .3s}.swagger-ui button{cursor:pointer}.swagger-ui button.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui .copy-to-clipboard{align-items:center;background:#7d8293;border:none;border-radius:4px;bottom:10px;display:flex;height:30px;justify-content:center;position:absolute;right:100px;width:30px}.swagger-ui .copy-to-clipboard button{background:url('data:image/svg+xml;charset=utf-8,') 50% no-repeat;border:none;flex-grow:1;flex-shrink:1;height:25px}.swagger-ui .curl-command .copy-to-clipboard{bottom:5px;height:20px;right:10px;width:20px}.swagger-ui .curl-command .copy-to-clipboard button{height:18px}.swagger-ui select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#f7f7f7 url('data:image/svg+xml;charset=utf-8,') right 10px center no-repeat;background-size:20px;border:2px solid #41444e;border-radius:4px;box-shadow:0 1px 2px 0 rgba(0,0,0,.25);color:#3b4151;font-family:sans-serif;font-size:14px;font-weight:700;padding:5px 40px 5px 10px}.swagger-ui select[multiple]{background:#f7f7f7;margin:5px 0;padding:5px}.swagger-ui select.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui .opblock-body select{min-width:230px}@media (max-width:768px){.swagger-ui .opblock-body select{min-width:180px}}.swagger-ui label{color:#3b4151;font-family:sans-serif;font-size:12px;font-weight:700;margin:0 0 5px}@media (max-width:768px){.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text]{max-width:175px}}.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text],.swagger-ui textarea{background:#fff;border:1px solid #d9d9d9;border-radius:4px;margin:5px 0;min-width:100px;padding:8px 10px}.swagger-ui input[type=email].invalid,.swagger-ui input[type=file].invalid,.swagger-ui input[type=password].invalid,.swagger-ui input[type=search].invalid,.swagger-ui input[type=text].invalid,.swagger-ui textarea.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui input[disabled],.swagger-ui select[disabled],.swagger-ui textarea[disabled]{background-color:#fafafa;color:#888;cursor:not-allowed}.swagger-ui select[disabled]{border-color:#888}.swagger-ui textarea[disabled]{background-color:#41444e;color:#fff}@-webkit-keyframes shake{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes shake{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}.swagger-ui textarea{background:hsla(0,0%,100%,.8);border:none;border-radius:4px;color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;min-height:280px;outline:none;padding:10px;width:100%}.swagger-ui textarea:focus{border:2px solid #61affe}.swagger-ui textarea.curl{background:#41444e;border-radius:4px;color:#fff;font-family:monospace;font-size:12px;font-weight:600;margin:0;min-height:100px;padding:10px;resize:none}.swagger-ui .checkbox{color:#303030;padding:5px 0 10px;transition:opacity .5s}.swagger-ui .checkbox label{display:flex}.swagger-ui .checkbox p{color:#3b4151;font-family:monospace;font-style:italic;font-weight:400!important;font-weight:600;margin:0!important}.swagger-ui .checkbox input[type=checkbox]{display:none}.swagger-ui .checkbox input[type=checkbox]+label>.item{background:#e8e8e8;border-radius:1px;box-shadow:0 0 0 2px #e8e8e8;cursor:pointer;display:inline-block;flex:none;height:16px;margin:0 8px 0 0;padding:5px;position:relative;top:3px;width:16px}.swagger-ui .checkbox input[type=checkbox]+label>.item:active{transform:scale(.9)}.swagger-ui .checkbox input[type=checkbox]:checked+label>.item{background:#e8e8e8 url('data:image/svg+xml;charset=utf-8,') 50% no-repeat}.swagger-ui .dialog-ux{bottom:0;left:0;position:fixed;right:0;top:0;z-index:9999}.swagger-ui .dialog-ux .backdrop-ux{background:rgba(0,0,0,.8);bottom:0;left:0;position:fixed;right:0;top:0}.swagger-ui .dialog-ux .modal-ux{background:#fff;border:1px solid #ebebeb;border-radius:4px;box-shadow:0 10px 30px 0 rgba(0,0,0,.2);left:50%;max-width:650px;min-width:300px;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%;z-index:9999}.swagger-ui .dialog-ux .modal-ux-content{max-height:540px;overflow-y:auto;padding:20px}.swagger-ui .dialog-ux .modal-ux-content p{color:#41444e;color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px}.swagger-ui .dialog-ux .modal-ux-content h4{color:#3b4151;font-family:sans-serif;font-size:18px;font-weight:600;margin:15px 0 0}.swagger-ui .dialog-ux .modal-ux-header{align-items:center;border-bottom:1px solid #ebebeb;display:flex;padding:12px 0}.swagger-ui .dialog-ux .modal-ux-header .close-modal{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;padding:0 10px}.swagger-ui .dialog-ux .modal-ux-header h3{color:#3b4151;flex:1;font-family:sans-serif;font-size:20px;font-weight:600;margin:0;padding:0 20px}.swagger-ui .model{color:#3b4151;font-family:monospace;font-size:12px;font-weight:300;font-weight:600}.swagger-ui .model .deprecated span,.swagger-ui .model .deprecated td{color:#a0a0a0!important}.swagger-ui .model .deprecated>td:first-of-type{text-decoration:line-through}.swagger-ui .model-toggle{cursor:pointer;display:inline-block;font-size:10px;margin:auto .3em;position:relative;top:6px;transform:rotate(90deg);transform-origin:50% 50%;transition:transform .15s ease-in}.swagger-ui .model-toggle.collapsed{transform:rotate(0deg)}.swagger-ui .model-toggle:after{background:url('data:image/svg+xml;charset=utf-8,') 50% no-repeat;background-size:100%;content:"";display:block;height:20px;width:20px}.swagger-ui .model-jump-to-path{cursor:pointer;position:relative}.swagger-ui .model-jump-to-path .view-line-link{cursor:pointer;position:absolute;top:-.4em}.swagger-ui .model-title{position:relative}.swagger-ui .model-title:hover .model-hint{visibility:visible}.swagger-ui .model-hint{background:rgba(0,0,0,.7);border-radius:4px;color:#ebebeb;padding:.1em .5em;position:absolute;top:-1.8em;visibility:hidden;white-space:nowrap}.swagger-ui .model p{margin:0 0 1em}.swagger-ui .model .property{color:#999;font-style:italic}.swagger-ui .model .property.primitive{color:#6b6b6b}.swagger-ui table.model tr.description{color:#666;font-weight:400}.swagger-ui table.model tr.description td:first-child,.swagger-ui table.model tr.property-row.required td:first-child{font-weight:700}.swagger-ui table.model tr.property-row td{vertical-align:top}.swagger-ui table.model tr.property-row td:first-child{padding-right:.2em}.swagger-ui table.model tr.property-row .star{color:red}.swagger-ui table.model tr.extension{color:#777}.swagger-ui table.model tr.extension td:last-child{vertical-align:top}.swagger-ui section.models{border:1px solid rgba(59,65,81,.3);border-radius:4px;margin:30px 0}.swagger-ui section.models .pointer{cursor:pointer}.swagger-ui section.models.is-open{padding:0 0 20px}.swagger-ui section.models.is-open h4{border-bottom:1px solid rgba(59,65,81,.3);margin:0 0 5px}.swagger-ui section.models h4{align-items:center;color:#606060;cursor:pointer;display:flex;font-family:sans-serif;font-size:16px;margin:0;padding:10px 20px 10px 10px;transition:all .2s}.swagger-ui section.models h4 svg{transition:all .4s}.swagger-ui section.models h4 span{flex:1}.swagger-ui section.models h4:hover{background:rgba(0,0,0,.02)}.swagger-ui section.models h5{color:#707070;font-family:sans-serif;font-size:16px;margin:0 0 10px}.swagger-ui section.models .model-jump-to-path{position:relative;top:5px}.swagger-ui section.models .model-container{background:rgba(0,0,0,.05);border-radius:4px;margin:0 20px 15px;position:relative;transition:all .5s}.swagger-ui section.models .model-container:hover{background:rgba(0,0,0,.07)}.swagger-ui section.models .model-container:first-of-type{margin:20px}.swagger-ui section.models .model-container:last-of-type{margin:0 20px}.swagger-ui section.models .model-container .models-jump-to-path{opacity:.65;position:absolute;right:5px;top:8px}.swagger-ui section.models .model-box{background:none}.swagger-ui .model-box{background:rgba(0,0,0,.1);border-radius:4px;display:inline-block;padding:10px}.swagger-ui .model-box .model-jump-to-path{position:relative;top:4px}.swagger-ui .model-box.deprecated{opacity:.5}.swagger-ui .model-title{color:#505050;font-family:sans-serif;font-size:16px}.swagger-ui .model-title img{bottom:0;margin-left:1em;position:relative}.swagger-ui .model-deprecated-warning{color:#f93e3e;font-family:sans-serif;font-size:16px;font-weight:600;margin-right:1em}.swagger-ui span>span.model .brace-close{padding:0 0 0 10px}.swagger-ui .prop-name{display:inline-block;margin-right:1em}.swagger-ui .prop-type{color:#55a}.swagger-ui .prop-enum{display:block}.swagger-ui .prop-format{color:#606060}.swagger-ui .servers>label{color:#3b4151;font-family:sans-serif;font-size:12px;margin:-20px 15px 0 0}.swagger-ui .servers>label select{max-width:100%;min-width:130px}.swagger-ui .servers h4.message{padding-bottom:2em}.swagger-ui .servers table tr{width:30em}.swagger-ui .servers table td{display:inline-block;max-width:15em;padding-bottom:10px;padding-top:10px;vertical-align:middle}.swagger-ui .servers table td:first-of-type{padding-right:1em}.swagger-ui .servers table td input{height:100%;width:100%}.swagger-ui .servers .computed-url{margin:2em 0}.swagger-ui .servers .computed-url code{display:inline-block;font-size:16px;margin:0 1em;padding:4px}.swagger-ui .servers-title{font-size:12px;font-weight:700}.swagger-ui .operation-servers h4.message{margin-bottom:2em}.swagger-ui table{border-collapse:collapse;padding:0 10px;width:100%}.swagger-ui table.model tbody tr td{padding:0;vertical-align:top}.swagger-ui table.model tbody tr td:first-of-type{padding:0 0 0 2em;width:174px}.swagger-ui table.headers td{color:#3b4151;font-family:monospace;font-size:12px;font-weight:300;font-weight:600;vertical-align:middle}.swagger-ui table.headers .header-example{color:#999;font-style:italic}.swagger-ui table tbody tr td{padding:10px 0 0;vertical-align:top}.swagger-ui table tbody tr td:first-of-type{min-width:6em;padding:10px 0}.swagger-ui table thead tr td,.swagger-ui table thead tr th{border-bottom:1px solid rgba(59,65,81,.2);color:#3b4151;font-family:sans-serif;font-size:12px;font-weight:700;padding:12px 0;text-align:left}.swagger-ui .parameters-col_description{margin-bottom:2em;width:99%}.swagger-ui .parameters-col_description input[type=text]{max-width:340px;width:100%}.swagger-ui .parameters-col_description select{border-width:1px}.swagger-ui .parameter__name{color:#3b4151;font-family:sans-serif;font-size:16px;font-weight:400;margin-right:.75em}.swagger-ui .parameter__name.required{font-weight:700}.swagger-ui .parameter__name.required span{color:red}.swagger-ui .parameter__name.required:after{color:rgba(255,0,0,.6);content:"required";font-size:10px;padding:5px;position:relative;top:-6px}.swagger-ui .parameter__extension,.swagger-ui .parameter__in{color:gray;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .parameter__deprecated{color:red;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .parameter__empty_value_toggle{display:block;font-size:13px;padding-bottom:12px;padding-top:5px}.swagger-ui .parameter__empty_value_toggle input{margin-right:7px}.swagger-ui .parameter__empty_value_toggle.disabled{opacity:.7}.swagger-ui .table-container{padding:20px}.swagger-ui .response-col_description{width:99%}.swagger-ui .response-col_links{min-width:6em}.swagger-ui .response__extension{color:gray;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .topbar{background-color:#1b1b1b;padding:10px 0}.swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a{align-items:center;display:flex}.swagger-ui .topbar a{color:#fff;flex:1;font-family:sans-serif;font-size:1.5em;font-weight:700;max-width:300px;text-decoration:none}.swagger-ui .topbar a span{margin:0;padding:0 10px}.swagger-ui .topbar .download-url-wrapper{display:flex;flex:3;justify-content:flex-end}.swagger-ui .topbar .download-url-wrapper input[type=text]{border:2px solid #62a03f;border-radius:4px 0 0 4px;margin:0;outline:none;width:100%}.swagger-ui .topbar .download-url-wrapper .select-label{align-items:center;color:#f0f0f0;display:flex;margin:0;max-width:600px;width:100%}.swagger-ui .topbar .download-url-wrapper .select-label span{flex:1;font-size:16px;padding:0 10px 0 0;text-align:right}.swagger-ui .topbar .download-url-wrapper .select-label select{border:2px solid #62a03f;box-shadow:none;flex:2;outline:none;width:100%}.swagger-ui .topbar .download-url-wrapper .download-url-button{background:#62a03f;border:none;border-radius:0 4px 4px 0;color:#fff;font-family:sans-serif;font-size:16px;font-weight:700;padding:4px 30px}.swagger-ui .info{margin:50px 0}.swagger-ui .info.failed-config{margin-left:auto;margin-right:auto;max-width:880px;text-align:center}.swagger-ui .info hgroup.main{margin:0 0 20px}.swagger-ui .info hgroup.main a{font-size:12px}.swagger-ui .info pre{font-size:14px}.swagger-ui .info li,.swagger-ui .info p,.swagger-ui .info table{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .info h1,.swagger-ui .info h2,.swagger-ui .info h3,.swagger-ui .info h4,.swagger-ui .info h5{color:#3b4151;font-family:sans-serif}.swagger-ui .info a{color:#4990e2;font-family:sans-serif;font-size:14px;transition:all .4s}.swagger-ui .info a:hover{color:#1f69c0}.swagger-ui .info>div{margin:0 0 5px}.swagger-ui .info .base-url{color:#3b4151;font-family:monospace;font-size:12px;font-weight:300!important;font-weight:600;margin:0}.swagger-ui .info .title{color:#3b4151;font-family:sans-serif;font-size:36px;margin:0}.swagger-ui .info .title small{background:#7d8492;border-radius:57px;display:inline-block;font-size:10px;margin:0 0 0 5px;padding:2px 4px;position:relative;top:-5px;vertical-align:super}.swagger-ui .info .title small.version-stamp{background-color:#89bf04}.swagger-ui .info .title small pre{color:#fff;font-family:sans-serif;margin:0;padding:0}.swagger-ui .auth-btn-wrapper{display:flex;justify-content:center;padding:10px 0}.swagger-ui .auth-btn-wrapper .btn-done{margin-right:1em}.swagger-ui .auth-wrapper{display:flex;flex:1;justify-content:flex-end}.swagger-ui .auth-wrapper .authorize{margin-right:10px;padding-right:20px}.swagger-ui .auth-container{border-bottom:1px solid #ebebeb;margin:0 0 10px;padding:10px 20px}.swagger-ui .auth-container:last-of-type{border:0;margin:0;padding:10px 20px}.swagger-ui .auth-container h4{margin:5px 0 15px!important}.swagger-ui .auth-container .wrapper{margin:0;padding:0}.swagger-ui .auth-container input[type=password],.swagger-ui .auth-container input[type=text]{min-width:230px}.swagger-ui .auth-container .errors{background-color:#fee;border-radius:4px;color:red;color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;margin:1em;padding:10px}.swagger-ui .auth-container .errors b{margin-right:1em;text-transform:capitalize}.swagger-ui .scopes h2{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .scopes h2 a{color:#4990e2;cursor:pointer;font-size:12px;padding-left:10px;text-decoration:underline}.swagger-ui .scope-def{padding:0 0 20px}.swagger-ui .errors-wrapper{-webkit-animation:scaleUp .5s;animation:scaleUp .5s;background:rgba(249,62,62,.1);border:2px solid #f93e3e;border-radius:4px;margin:20px;padding:10px 20px}.swagger-ui .errors-wrapper .error-wrapper{margin:0 0 10px}.swagger-ui .errors-wrapper .errors h4{color:#3b4151;font-family:monospace;font-size:14px;font-weight:600;margin:0}.swagger-ui .errors-wrapper .errors small{color:#606060}.swagger-ui .errors-wrapper .errors .message{white-space:pre-line}.swagger-ui .errors-wrapper .errors .message.thrown{max-width:100%}.swagger-ui .errors-wrapper .errors .error-line{cursor:pointer;text-decoration:underline}.swagger-ui .errors-wrapper hgroup{align-items:center;display:flex}.swagger-ui .errors-wrapper hgroup h4{color:#3b4151;flex:1;font-family:sans-serif;font-size:20px;margin:0}@-webkit-keyframes scaleUp{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes scaleUp{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}.swagger-ui .Resizer.vertical.disabled{display:none}.swagger-ui .markdown p,.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown p,.swagger-ui .renderedMarkdown pre{margin:1em auto;word-break:break-all;word-break:break-word}.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown pre{background:none;color:#000;font-weight:400;padding:0;white-space:pre-wrap}.swagger-ui .markdown code,.swagger-ui .renderedMarkdown code{background:rgba(0,0,0,.05);border-radius:4px;color:#9012fe;font-family:monospace;font-size:14px;font-weight:600;padding:5px 7px}.swagger-ui .markdown pre>code,.swagger-ui .renderedMarkdown pre>code{display:block} + +/*# sourceMappingURL=swagger-ui.css.map*/ \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/application.yml b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/application.yml new file mode 100644 index 0000000000..e4bcdb5888 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/resources/application.yml @@ -0,0 +1,9 @@ +keycloak: + auth-server-url: https://api.example.com/auth # Keycloak server url + realm: todos-service-realm # Keycloak Realm + resource: todos-service-clients # Keycloak Client + public-client: true + principal-attribute: preferred_username + ssl-required: external + credentials: + secret: 00000000-0000-0000-0000-000000000000 diff --git a/spring-boot-modules/spring-boot-swagger/README.md b/spring-boot-modules/spring-boot-swagger/README.md index f94ae75c41..174bfe626d 100644 --- a/spring-boot-modules/spring-boot-swagger/README.md +++ b/spring-boot-modules/spring-boot-swagger/README.md @@ -2,3 +2,6 @@ - [Hiding Endpoints From Swagger Documentation in Spring Boot](https://www.baeldung.com/spring-swagger-hiding-endpoints) - [Swagger @Api Description Is Deprecated](https://www.baeldung.com/java-swagger-api-description-deprecated) +- [Generate PDF from Swagger API Documentation](https://www.baeldung.com/swagger-generate-pdf) +- [Remove Basic Error Controller In SpringFox Swagger-UI](https://www.baeldung.com/spring-swagger-remove-error-controller) +- [Setting Example and Description with Swagger](https://www.baeldung.com/swagger-set-example-description) diff --git a/spring-boot-modules/spring-boot-swagger/pom.xml b/spring-boot-modules/spring-boot-swagger/pom.xml index a9d8a943e4..b6ed50534e 100644 --- a/spring-boot-modules/spring-boot-swagger/pom.xml +++ b/spring-boot-modules/spring-boot-swagger/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -26,6 +25,11 @@ springfox-boot-starter ${springfox.version} + + com.github.kongchen + swagger-maven-plugin + ${swagger-maven-plugin.version} + @@ -34,11 +38,50 @@ org.springframework.boot spring-boot-maven-plugin + + com.github.kongchen + swagger-maven-plugin + ${swagger-maven-plugin.version} + + + + false + com.baeldung.swaggerenums.controller + http,https + baeldung.com + /api + + Baeldung - Document Enum + v1 + This is a Baeldung Document Enum Sample Code + + pmurria@baeldung.com + Parikshit Murria + + + https://www.apache.org/licenses/LICENSE-2.0.html + Apache 2.0 + + + ${basedir}/target/swagger-ui + + + + + + compile + + generate + + + + 3.0.0 + 3.1.1 - \ No newline at end of file + diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/SpringBootSwaggerConfApplication.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/SpringBootSwaggerConfApplication.java new file mode 100644 index 0000000000..1d2e129f26 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/SpringBootSwaggerConfApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerconf; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootSwaggerConfApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootSwaggerConfApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/configuration/SwaggerConfiguration.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/configuration/SwaggerConfiguration.java new file mode 100644 index 0000000000..a78335a2fe --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/configuration/SwaggerConfiguration.java @@ -0,0 +1,37 @@ +package com.baeldung.swaggerconf.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Collections; + +import static springfox.documentation.builders.PathSelectors.regex; + +@Configuration +@EnableSwagger2 +public class SwaggerConfiguration { + + private ApiInfo apiInfo() { + return new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", + new Contact("General UserName", "www.baeldung.com", "user-name@gmail.com"), + "License of API", "API license URL", Collections.emptyList()); + } + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.baeldung.swaggerconf.controller")) + .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) + .paths(regex("/good-path/.*")) + .build(); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForAnnotation.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForAnnotation.java new file mode 100644 index 0000000000..65059bf446 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForAnnotation.java @@ -0,0 +1,17 @@ +package com.baeldung.swaggerconf.controller; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; + +@Component +@RequestMapping("good-path/error-excluded-annotation") +public class ErrorControllerExcludedForAnnotation extends BasicErrorController { + + public ErrorControllerExcludedForAnnotation(ErrorAttributes errorAttributes, ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForApiIgnore.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForApiIgnore.java new file mode 100644 index 0000000000..88208d8446 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForApiIgnore.java @@ -0,0 +1,21 @@ +package com.baeldung.swaggerconf.controller; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.annotations.ApiIgnore; + +@Component +@RequestMapping("good-path/error-excluded-apiignore") +@RestController +@ApiIgnore +public class ErrorControllerExcludedForApiIgnore extends BasicErrorController { + + public ErrorControllerExcludedForApiIgnore(ErrorAttributes errorAttributes, ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForPath.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForPath.java new file mode 100644 index 0000000000..5cea4f5ef9 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/ErrorControllerExcludedForPath.java @@ -0,0 +1,19 @@ +package com.baeldung.swaggerconf.controller; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Component +@RequestMapping("wrong-path/error-excluded-path") +@RestController +public class ErrorControllerExcludedForPath extends BasicErrorController { + + public ErrorControllerExcludedForPath(ErrorAttributes errorAttributes, ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/RegularRestController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/RegularRestController.java new file mode 100644 index 0000000000..163826e626 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/controller/RegularRestController.java @@ -0,0 +1,33 @@ +package com.baeldung.swaggerconf.controller; + +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalTime; + +@RestController +@RequestMapping("good-path") +public class RegularRestController { + + @ApiOperation(value = "This method is used to get the author name.") + @GetMapping("/getAuthor") + public String getAuthor() { + return "Name Surname"; + } + + @ApiOperation(value = "This method is used to get the current date.") + @GetMapping("/getDate") + public LocalDate getDate() { + return LocalDate.now(); + } + + @ApiOperation(value = "This method is used to get the current time.") + @GetMapping("/getTime") + public LocalTime getTime() { + return LocalTime.now(); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/excluded/ErrorControllerExcludedForPackage.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/excluded/ErrorControllerExcludedForPackage.java new file mode 100644 index 0000000000..a3b5a3fe63 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerconf/excluded/ErrorControllerExcludedForPackage.java @@ -0,0 +1,17 @@ +package com.baeldung.swaggerconf.excluded; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; + +@Component +@RequestMapping("good-path/error-excluded-package") +public class ErrorControllerExcludedForPackage extends BasicErrorController { + + public ErrorControllerExcludedForPackage(ErrorAttributes errorAttributes, ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/SwaggerEnumsApplication.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/SwaggerEnumsApplication.java new file mode 100644 index 0000000000..0bb80df65f --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/SwaggerEnumsApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerenums; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SwaggerEnumsApplication { + + public static void main(String[] args) { + SpringApplication.run(SwaggerEnumsApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java new file mode 100644 index 0000000000..7b7bfdc2c5 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java @@ -0,0 +1,22 @@ +package com.baeldung.swaggerenums.controller; + +import com.baeldung.swaggerenums.model.Employee; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +@Api +@Path(value="/hire") +@Produces({"application/json"}) +public class HireController { + + @POST + @ApiOperation(value = "This method is used to hire employee with a specific role") + public String hireEmployee(@ApiParam(value = "role", required = true) Employee employee) { + return String.format("Hired for role: %s", employee.role.name()); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Employee.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Employee.java new file mode 100644 index 0000000000..ce9e5089c9 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Employee.java @@ -0,0 +1,17 @@ +package com.baeldung.swaggerenums.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel +public class Employee { + @ApiModelProperty + public Role role; + + public Role getRole() { + return role; + } + public void setRole(Role role) { + this.role = role; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Role.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Role.java new file mode 100644 index 0000000000..fa62b2d0b5 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/model/Role.java @@ -0,0 +1,8 @@ +package com.baeldung.swaggerenums.model; + +import io.swagger.annotations.ApiModel; + +@ApiModel +public enum Role { + Engineer, Clerk, Driver, Janitor; +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/SwaggerExampleApplication.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/SwaggerExampleApplication.java new file mode 100644 index 0000000000..4859224bb2 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/SwaggerExampleApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerexample; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SwaggerExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(SwaggerExampleApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/config/SwaggerConfig.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/config/SwaggerConfig.java new file mode 100644 index 0000000000..32dbe87bae --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/config/SwaggerConfig.java @@ -0,0 +1,38 @@ +package com.baeldung.swaggerexample.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.Collections; + +@Configuration +@EnableWebMvc +public class SwaggerConfig { + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.baeldung.swaggerexample")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfo( + "Products API", + "API to let you add and view product", + "0.0.1", + "Terms of service", + new Contact("John Doe", "www.example.com", "myemail@company.com"), + "License of API", "API license URL", Collections.emptyList()); + } +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/controller/ProductController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/controller/ProductController.java new file mode 100644 index 0000000000..7500c01bc0 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/controller/ProductController.java @@ -0,0 +1,34 @@ +package com.baeldung.swaggerexample.controller; + +import com.baeldung.swaggerexample.entity.Product; +import io.swagger.annotations.*; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@ApiOperation("Products API") +public class ProductController { + + @ApiOperation(value = "Create a new product", notes = "Creates a new product as per the request body") + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Successfully created"), + @ApiResponse(code = 400, message = "Bad request - The product is not valid"), + @ApiResponse(code = 500, message = "Internal server error - Something went wrong") + }) + @PostMapping(value = "/products") + public ResponseEntity createProduct(@RequestBody Product product) { + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @ApiOperation(value = "Get a product by id", notes = "Returns a product as per the id") + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successfully retrieved"), + @ApiResponse(code = 404, message = "Not found - The product was not found") + }) + @GetMapping("/products/{id}") + public ResponseEntity getProduct(@PathVariable("id") @ApiParam(name = "id", value = "Product id", example = "1") Long id) { + //retrieval logic + return ResponseEntity.ok(new Product(1, "Product 1", "$21.99")); + } +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/entity/Product.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/entity/Product.java new file mode 100644 index 0000000000..122addadd5 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerexample/entity/Product.java @@ -0,0 +1,46 @@ +package com.baeldung.swaggerexample.entity; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +public class Product implements Serializable { + @ApiModelProperty(notes = "Product ID", example = "1", required = true) + private Long id; + @ApiModelProperty(notes = "Product name", example = "Product 1", required = false) + private String name; + @ApiModelProperty(notes = "Product price", example = "$100.00", required = true) + private String price; + + // constructor and getter/setters + + public Product(long id, String name, String price) { + this.id = id; + this.name = name; + this.price = price; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/resources/application.properties b/spring-boot-modules/spring-boot-swagger/src/main/resources/application.properties index e69de29bb2..a4e98652bc 100644 --- a/spring-boot-modules/spring-boot-swagger/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-swagger/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.mvc.pathmatch.matching-strategy = ANT_PATH_MATCHER \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerconf/SwaggerConfExcludeErrorControllerIntegrationTest.java b/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerconf/SwaggerConfExcludeErrorControllerIntegrationTest.java new file mode 100644 index 0000000000..c0a5c54d69 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerconf/SwaggerConfExcludeErrorControllerIntegrationTest.java @@ -0,0 +1,33 @@ +package com.baeldung.swaggerconf; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@AutoConfigureMockMvc +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class SwaggerConfExcludeErrorControllerIntegrationTest { + + @Autowired + private MockMvc mvc; + + @Test + public void whenCallingSwaggerJSON_stringObjectDoesNotContainAnyErrorControllers() throws Exception { + ResultActions resultActions = mvc.perform(get("/v2/api-docs")).andExpect(status().isOk()); + MvcResult result = resultActions.andReturn(); + String content = result.getResponse().getContentAsString(); + Assert.assertNotNull(content); + Assert.assertFalse(content.contains("error-controller")); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerenums/controller/HireControllerUnitTest.java b/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerenums/controller/HireControllerUnitTest.java new file mode 100644 index 0000000000..b2ec5ccaa5 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/test/java/com/baeldung/swaggerenums/controller/HireControllerUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.swaggerenums.controller; + +import com.baeldung.swaggerenums.model.Employee; +import com.baeldung.swaggerenums.model.Role; +import org.junit.Assert; +import org.junit.Test; + +public class HireControllerUnitTest { + + @Test + public void givenRoleEngineer_whenHireEmployee_thenReturnsRoleInString() { + //Arrange + Role testRole = Role.Engineer; + Employee employee = new Employee(); + employee.setRole(testRole); + + //Act + HireController hireController = new HireController(); + String response = hireController.hireEmployee(employee); + + //Assert + Assert.assertEquals(String.format("Hired for role: %s", testRole), + response); + } +} diff --git a/guest/spring-boot-app/.gitignore b/spring-boot-modules/spring-boot-testing-2/.gitignore similarity index 97% rename from guest/spring-boot-app/.gitignore rename to spring-boot-modules/spring-boot-testing-2/.gitignore index 60be5b80aa..da7c2c5c0a 100644 --- a/guest/spring-boot-app/.gitignore +++ b/spring-boot-modules/spring-boot-testing-2/.gitignore @@ -2,3 +2,4 @@ .settings/ .classpath .project + diff --git a/spring-boot-modules/spring-boot-testing-2/README.md b/spring-boot-modules/spring-boot-testing-2/README.md new file mode 100644 index 0000000000..33664a4448 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/README.md @@ -0,0 +1,12 @@ +## Spring Boot Testing + +This module contains articles about Spring Boot testing + +### The Course + +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: + +- [Setting the Log Level in Spring Boot when Testing](https://www.baeldung.com/spring-boot-testing-log-level) +- More articles: [[<-- prev]](../spring-boot-testing) \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing-2/pom.xml b/spring-boot-modules/spring-boot-testing-2/pom.xml new file mode 100644 index 0000000000..dfe41d684d --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + spring-boot-testing-2 + spring-boot-testing-2 + jar + This is simple boot application for demonstrating testing features. + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + com.baeldung.boot.Application + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/boot/Application.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/boot/Application.java new file mode 100644 index 0000000000..a78bb0410b --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/boot/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/component/OtherComponent.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/component/OtherComponent.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/component/OtherComponent.java rename to spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/component/OtherComponent.java diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java rename to spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java rename to spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-testing-2/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/boot/SpringContextTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/boot/SpringContextTest.java new file mode 100644 index 0000000000..f3c8b9a954 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/boot/SpringContextTest.java @@ -0,0 +1,15 @@ +package com.baeldung.boot; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java rename to spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java rename to spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java rename to spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/application-logback-test.properties b/spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logback-test.properties similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/resources/application-logback-test.properties rename to spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logback-test.properties diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/application-logback-test2.properties b/spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logback-test2.properties similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/resources/application-logback-test2.properties rename to spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logback-test2.properties diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/application-logging-test.properties b/spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logging-test.properties similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/resources/application-logging-test.properties rename to spring-boot-modules/spring-boot-testing-2/src/test/resources/application-logging-test.properties diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/resources/application.properties b/spring-boot-modules/spring-boot-testing-2/src/test/resources/application.properties new file mode 100644 index 0000000000..2b406d1c6e --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/resources/application.properties @@ -0,0 +1,3 @@ +# logging.level.com.baeldung.testloglevel=DEBUG + +# logging.level.root=INFO diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/logback-multiprofile.xml b/spring-boot-modules/spring-boot-testing-2/src/test/resources/logback-multiprofile.xml similarity index 100% rename from spring-boot-modules/spring-boot-testing/src/test/resources/logback-multiprofile.xml rename to spring-boot-modules/spring-boot-testing-2/src/test/resources/logback-multiprofile.xml diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-testing-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..0528aa88f3 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/spring-boot-modules/spring-boot-testing/README.md b/spring-boot-modules/spring-boot-testing/README.md index 058c78c9bb..2fb96992c9 100644 --- a/spring-boot-modules/spring-boot-testing/README.md +++ b/spring-boot-modules/spring-boot-testing/README.md @@ -10,9 +10,10 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Testing with Spring and Spock](https://www.baeldung.com/spring-spock-testing) - [Exclude Auto-Configuration Classes in Spring Boot Tests](https://www.baeldung.com/spring-boot-exclude-auto-configuration-test) -- [Setting the Log Level in Spring Boot when Testing](https://www.baeldung.com/spring-boot-testing-log-level) - [Embedded Redis Server with Spring Boot Test](https://www.baeldung.com/spring-embedded-redis) - [Testing Spring Boot @ConfigurationProperties](https://www.baeldung.com/spring-boot-testing-configurationproperties) - [Prevent ApplicationRunner or CommandLineRunner Beans From Executing During Junit Testing](https://www.baeldung.com/spring-junit-prevent-runner-beans-testing-execution) - [Testing in Spring Boot](https://www.baeldung.com/spring-boot-testing) - [Fixing the NoSuchMethodError JUnit Error](https://www.baeldung.com/junit-nosuchmethoderror) +- [Failed to Load ApplicationContext for JUnit Test of Spring Controller](https://www.baeldung.com/spring-junit-failed-to-load-applicationcontext) +- More articles: [[more -->]](../spring-boot-testing-2) diff --git a/spring-boot-modules/spring-boot-testing/pom.xml b/spring-boot-modules/spring-boot-testing/pom.xml index f70e77b31a..658eb7728e 100644 --- a/spring-boot-modules/spring-boot-testing/pom.xml +++ b/spring-boot-modules/spring-boot-testing/pom.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-testing - war spring-boot-testing + war This is simple boot application for demonstrating testing features. com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -49,17 +48,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - - it.ozimov diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/XmlBeanApplication.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/XmlBeanApplication.java new file mode 100644 index 0000000000..ddf1efd396 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/XmlBeanApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.xmlapplicationcontext; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportResource; + +@SpringBootApplication +@ImportResource({"classpath*:application-context.xml"}) +public class XmlBeanApplication { + + public static void main(String[] args) { + SpringApplication.run(XmlBeanApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/domain/Employee.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/domain/Employee.java new file mode 100644 index 0000000000..f81277f027 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/domain/Employee.java @@ -0,0 +1,32 @@ +package com.baeldung.xmlapplicationcontext.domain; + +public class Employee { + + private String name; + private String role; + + public Employee() { + + } + + public Employee(String name, String role) { + this.name = name; + this.role = role; + } + + public String getName() { + return this.name; + } + + public String getRole() { + return this.role; + } + + public void setName(String name) { + this.name = name; + } + + public void setRole(String role) { + this.role = role; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeService.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeService.java new file mode 100644 index 0000000000..867e9b8c9f --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeService.java @@ -0,0 +1,8 @@ +package com.baeldung.xmlapplicationcontext.service; + +import com.baeldung.xmlapplicationcontext.domain.Employee; + +public interface EmployeeService { + + Employee getEmployee(); +} diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceImpl.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceImpl.java new file mode 100644 index 0000000000..b541c62dcd --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceImpl.java @@ -0,0 +1,11 @@ +package com.baeldung.xmlapplicationcontext.service; + +import com.baeldung.xmlapplicationcontext.domain.Employee; + +public class EmployeeServiceImpl implements EmployeeService { + + @Override + public Employee getEmployee() { + return new Employee("Baeldung", "Admin"); + } +} diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceTestImpl.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceTestImpl.java new file mode 100644 index 0000000000..7cebaa399b --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/xmlapplicationcontext/service/EmployeeServiceTestImpl.java @@ -0,0 +1,11 @@ +package com.baeldung.xmlapplicationcontext.service; + +import com.baeldung.xmlapplicationcontext.domain.Employee; + +public class EmployeeServiceTestImpl implements EmployeeService { + + @Override + public Employee getEmployee() { + return new Employee("Baeldung-Test", "Admin"); + } +} diff --git a/spring-boot-modules/spring-boot-testing/src/main/resources/application-context.xml b/spring-boot-modules/spring-boot-testing/src/main/resources/application-context.xml new file mode 100644 index 0000000000..fc0e0fef25 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/resources/application-context.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/spring-boot-modules/spring-boot-testing/src/main/webapp/WEB-INF/application-context.xml b/spring-boot-modules/spring-boot-testing/src/main/webapp/WEB-INF/application-context.xml new file mode 100644 index 0000000000..fc0e0fef25 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/main/webapp/WEB-INF/application-context.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceAppContextIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceAppContextIntegrationTest.java new file mode 100644 index 0000000000..e9ee8f3951 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceAppContextIntegrationTest.java @@ -0,0 +1,27 @@ +package com.baeldung.xmlapplicationcontext; + +import com.baeldung.xmlapplicationcontext.service.EmployeeService; +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.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = XmlBeanApplication.class) +//@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/application-context.xml") +public class EmployeeServiceAppContextIntegrationTest { + + @Autowired + private EmployeeService service; + + @Test + public void whenContextLoads_thenServiceISNotNull() { + assertThat(service).isNotNull(); + } + +} diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceTestContextIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceTestContextIntegrationTest.java new file mode 100644 index 0000000000..0182d5dbb1 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/xmlapplicationcontext/EmployeeServiceTestContextIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.xmlapplicationcontext; + +import com.baeldung.xmlapplicationcontext.service.EmployeeService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = XmlBeanApplication.class) +@ContextConfiguration(locations = "/test-context.xml") +public class EmployeeServiceTestContextIntegrationTest { + + @Autowired + @Qualifier("employeeServiceTestImpl") + private EmployeeService serviceTest; + + @Test + public void whenTestContextLoads_thenServiceTestISNotNull() { + assertThat(serviceTest).isNotNull(); + } + +} diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-testing/src/test/resources/logback-test.xml index 0528aa88f3..9553dcad41 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/resources/logback-test.xml +++ b/spring-boot-modules/spring-boot-testing/src/test/resources/logback-test.xml @@ -9,5 +9,4 @@ - diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/test-context.xml b/spring-boot-modules/spring-boot-testing/src/test/resources/test-context.xml new file mode 100644 index 0000000000..fbd6da32ca --- /dev/null +++ b/spring-boot-modules/spring-boot-testing/src/test/resources/test-context.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/spring-boot-modules/spring-boot-validation/pom.xml b/spring-boot-modules/spring-boot-validation/pom.xml index 86e0a47d0d..fa4e8439e6 100644 --- a/spring-boot-modules/spring-boot-validation/pom.xml +++ b/spring-boot-modules/spring-boot-validation/pom.xml @@ -8,10 +8,9 @@ 0.0.1-SNAPSHOT - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT diff --git a/spring-boot-modules/spring-boot-validation/src/test/resources/logback-test.xml b/spring-boot-modules/spring-boot-validation/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-boot-modules/spring-boot-validation/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-vue/pom.xml b/spring-boot-modules/spring-boot-vue/pom.xml index 3d3d51797c..c552a9583f 100644 --- a/spring-boot-modules/spring-boot-vue/pom.xml +++ b/spring-boot-modules/spring-boot-vue/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot-vue 0.0.1-SNAPSHOT - jar spring-boot-vue + jar Demo project for Spring Boot Vue project com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ diff --git a/spring-boot-modules/spring-boot/README.md b/spring-boot-modules/spring-boot/README.md index 5a45502fd8..fdc8093806 100644 --- a/spring-boot-modules/spring-boot/README.md +++ b/spring-boot-modules/spring-boot/README.md @@ -8,12 +8,9 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [A Guide to Spring in Eclipse STS](https://www.baeldung.com/eclipse-sts-spring) -- [How to Register a Servlet in Java](https://www.baeldung.com/register-servlet) -- [Guide to Spring WebUtils and ServletRequestUtils](https://www.baeldung.com/spring-webutils-servletrequestutils) -- [Dynamic DTO Validation Config Retrieved from the Database](https://www.baeldung.com/spring-dynamic-dto-validation) - [Guide to Spring Type Conversions](https://www.baeldung.com/spring-type-conversions) - [Spring Boot: Configuring a Main Class](https://www.baeldung.com/spring-boot-main-class) -- [A Quick Intro to the SpringBootServletInitializer](https://www.baeldung.com/spring-boot-servlet-initializer) -- [Spring Shutdown Callbacks](https://www.baeldung.com/spring-shutdown-callbacks) - [Container Configuration in Spring Boot 2](https://www.baeldung.com/embeddedservletcontainercustomizer-configurableembeddedservletcontainer-spring-boot) - [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) +- [How to Register a Servlet in Java](https://www.baeldung.com/register-servlet) +- [Guide to Spring WebUtils and ServletRequestUtils](https://www.baeldung.com/spring-webutils-servletrequestutils) diff --git a/spring-boot-modules/spring-boot/pom.xml b/spring-boot-modules/spring-boot/pom.xml index 8df16a1f9c..3afccef925 100644 --- a/spring-boot-modules/spring-boot/pom.xml +++ b/spring-boot-modules/spring-boot/pom.xml @@ -5,15 +5,14 @@ 4.0.0 spring-boot 0.0.1-SNAPSHOT - war spring-boot + war This is simple boot application for Spring boot actuator test com.baeldung.spring-boot-modules spring-boot-modules 1.0.0-SNAPSHOT - ../ @@ -54,17 +53,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - - io.dropwizard.metrics metrics-core @@ -172,7 +160,6 @@ com.baeldung.intro.App 8.5.11 1.9.0 - 18.0 @ diff --git a/spring-boot-rest-2/README.md b/spring-boot-rest-2/README.md index 41270d58ea..985aa97a86 100644 --- a/spring-boot-rest-2/README.md +++ b/spring-boot-rest-2/README.md @@ -2,3 +2,4 @@ - [Get All Endpoints in Spring Boot](https://www.baeldung.com/spring-boot-get-all-endpoints) - [HTTP PUT vs. POST in REST API](https://www.baeldung.com/rest-http-put-vs-post) +- [415 Unsupported MediaType in Spring Application](https://www.baeldung.com/spring-415-unsupported-mediatype) diff --git a/spring-boot-rest-2/pom.xml b/spring-boot-rest-2/pom.xml index 0560d6c9c7..b75e93577a 100644 --- a/spring-boot-rest-2/pom.xml +++ b/spring-boot-rest-2/pom.xml @@ -28,7 +28,7 @@ io.springfox springfox-boot-starter - 3.0.0 + ${springfox.version} org.springframework.boot @@ -50,4 +50,8 @@ + + 3.0.0 + + \ No newline at end of file diff --git a/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UnsupportedMediaTypeApplication.java b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UnsupportedMediaTypeApplication.java new file mode 100644 index 0000000000..2bf6bb33cd --- /dev/null +++ b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UnsupportedMediaTypeApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.unsupportedmediatype; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class UnsupportedMediaTypeApplication { + + public static void main(String[] args) { + SpringApplication.run(UnsupportedMediaTypeApplication.class, args); + } + +} diff --git a/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/User.java b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/User.java new file mode 100644 index 0000000000..765149dad5 --- /dev/null +++ b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/User.java @@ -0,0 +1,66 @@ +package com.baeldung.unsupportedmediatype; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +@XmlRootElement +public class User implements Serializable { + private Integer id; + private String name; + private Integer age; + private String address; + + public User(){ + } + + public User(Integer id, String name, Integer age, String address) { + this.id = id; + this.name = name; + this.age = age; + this.address = address; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", name='" + name + '\'' + + ", age=" + age + + ", address='" + address + '\'' + + '}'; + } + + +} diff --git a/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UserController.java b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UserController.java new file mode 100644 index 0000000000..a20043619a --- /dev/null +++ b/spring-boot-rest-2/src/main/java/com/baeldung/unsupportedmediatype/UserController.java @@ -0,0 +1,29 @@ +package com.baeldung.unsupportedmediatype; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; + +@RestController +@RequestMapping("/user") +public class UserController { + + @GetMapping(value = "/") + List getAllUsers(){ + return Collections.singletonList(new User(1, "Andy", 28, "14th Street")); + } + + @GetMapping(value = "/{user-id}") + User getUser(@PathVariable("user-id") Integer userId){ + return new User(userId, "Andy", 28, "14th Street"); + } + + @PostMapping(value = "/", consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) + void AddUser(@RequestBody User user){ + // Adding the User in the repository + } + + +} \ No newline at end of file diff --git a/spring-boot-rest-2/src/test/java/com/baeldung/unsupportedmediatype/ApplicationUnitTest.java b/spring-boot-rest-2/src/test/java/com/baeldung/unsupportedmediatype/ApplicationUnitTest.java new file mode 100644 index 0000000000..498ad9d537 --- /dev/null +++ b/spring-boot-rest-2/src/test/java/com/baeldung/unsupportedmediatype/ApplicationUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.unsupportedmediatype; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(UserController.class) +public class ApplicationUnitTest { + @Autowired + private MockMvc mockMvc; + + @Test + public void JsonTestCase() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/user/") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content( "{\n" + + " \"name\": \"Andy\",\n" + + " \"age\": 1,\n" + + " \"address\": \"Hello world\"\n" + + "}")) + .andExpect(status().isOk()); + } + + @Test + public void JsonFailTestCase() throws Exception {// Because no content-type added + mockMvc.perform(MockMvcRequestBuilders.post("/user/") + .content( "{\n" + + " \"name\": \"Andy\",\n" + + " \"age\": 1,\n" + + " \"address\": \"Hello world\"\n" + + "}")) + .andExpect(status().isUnsupportedMediaType()); + } + + @Test + public void XmlTestCase() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/user/") + .contentType(MediaType.APPLICATION_XML_VALUE) + .content("Andy1
Hello world
")) + .andExpect(status().isOk()); + } + + @Test + public void StringFailTestCase() throws Exception { // Because content-type is not supported + mockMvc.perform(MockMvcRequestBuilders.post("/user/") + .contentType(MediaType.TEXT_PLAIN_VALUE) + .content("Andy1
Hello world
")) + .andExpect(status().isUnsupportedMediaType()); + } +} diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 72d4ecfaa6..cbd59ef78e 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -86,9 +86,8 @@ com.baeldung.SpringBootRestApplication - 27.0.1-jre 1.4.11.1 - 2.3.5 + 2.4.5 \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/springpagination/controller/PostRestController.java b/spring-boot-rest/src/main/java/com/baeldung/springpagination/controller/PostRestController.java index c52960b365..500de17e1e 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/springpagination/controller/PostRestController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/springpagination/controller/PostRestController.java @@ -19,6 +19,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import java.text.ParseException; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; @Controller @@ -65,7 +66,11 @@ public class PostRestController { @PutMapping(value = "/{id}") @ResponseStatus(HttpStatus.OK) - public void updatePost(@RequestBody PostDto postDto) throws ParseException { + public void updatePost(@PathVariable("id") Long id, @RequestBody PostDto postDto) throws ParseException { + if(!Objects.equals(id, postDto.getId())){ + throw new IllegalArgumentException("IDs don't match"); + } + Post post = convertToEntity(postDto); postService.updatePost(post); } diff --git a/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java b/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java index caf1df2a1b..e653e84048 100644 --- a/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java +++ b/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java @@ -1,8 +1,12 @@ package com.baeldung.ehcache.calculator; import com.baeldung.ehcache.config.CacheHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SquaredCalculator { + + private static final Logger LOGGER = LoggerFactory.getLogger(SquaredCalculator.class); private CacheHelper cache; public int getSquareValueOfNumber(int input) { @@ -10,7 +14,7 @@ public class SquaredCalculator { return cache.getSquareNumberCache().get(input); } - System.out.println("Calculating square value of " + input + " and caching result."); + LOGGER.debug("Calculating square value of {} and caching result.", input); int squaredValue = (int) Math.pow(input, 2); cache.getSquareNumberCache().put(input, squaredValue); diff --git a/spring-caching/src/main/resources/logback.xml b/spring-caching/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-caching/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/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java b/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java index 37df749bab..6a6c51bd9e 100644 --- a/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java +++ b/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java @@ -4,13 +4,18 @@ import com.baeldung.ehcache.calculator.SquaredCalculator; import com.baeldung.ehcache.config.CacheHelper; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class SquareCalculatorUnitTest { - private SquaredCalculator squaredCalculator = new SquaredCalculator(); - private CacheHelper cacheHelper = new CacheHelper(); + + private static final Logger LOGGER = LoggerFactory.getLogger(SquareCalculatorUnitTest.class); + + private final SquaredCalculator squaredCalculator = new SquaredCalculator(); + private final CacheHelper cacheHelper = new CacheHelper(); @Before public void setup() { @@ -21,7 +26,7 @@ public class SquareCalculatorUnitTest { public void whenCalculatingSquareValueOnce_thenCacheDontHaveValues() { for (int i = 10; i < 15; i++) { assertFalse(cacheHelper.getSquareNumberCache().containsKey(i)); - System.out.println("Square value of " + i + " is: " + squaredCalculator.getSquareValueOfNumber(i) + "\n"); + LOGGER.debug("Square value of {} is: {}", i, squaredCalculator.getSquareValueOfNumber(i)); } } @@ -29,12 +34,12 @@ public class SquareCalculatorUnitTest { public void whenCalculatingSquareValueAgain_thenCacheHasAllValues() { for (int i = 10; i < 15; i++) { assertFalse(cacheHelper.getSquareNumberCache().containsKey(i)); - System.out.println("Square value of " + i + " is: " + squaredCalculator.getSquareValueOfNumber(i) + "\n"); + LOGGER.debug("Square value of {} is: {}", i, squaredCalculator.getSquareValueOfNumber(i)); } for (int i = 10; i < 15; i++) { assertTrue(cacheHelper.getSquareNumberCache().containsKey(i)); - System.out.println("Square value of " + i + " is: " + squaredCalculator.getSquareValueOfNumber(i) + "\n"); + LOGGER.debug("Square value of {} is: {}", i, squaredCalculator.getSquareValueOfNumber(i) + "\n"); } } } diff --git a/spring-cloud-bus/pom.xml b/spring-cloud-bus/pom.xml index 88bb766047..2eab7d52a9 100644 --- a/spring-cloud-bus/pom.xml +++ b/spring-cloud-bus/pom.xml @@ -34,7 +34,7 @@ - 2020.0.3 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud-bus/spring-cloud-config-client/src/main/resources/application.yml b/spring-cloud-bus/spring-cloud-config-client/src/main/resources/application.yml index fbbc6d138f..bb5c9607b8 100644 --- a/spring-cloud-bus/spring-cloud-config-client/src/main/resources/application.yml +++ b/spring-cloud-bus/spring-cloud-config-client/src/main/resources/application.yml @@ -1,5 +1,11 @@ --- spring: + application: + name: config-client + profiles: + active: development + config: + import: configserver:http://root:s3cr3t@localhost:8888 rabbitmq: host: localhost port: 5672 @@ -10,8 +16,12 @@ spring: enabled: true refresh: enabled: true + config: + fail-fast: true management: endpoints: web: exposure: - include: "*" \ No newline at end of file + include: "*" + security: + enabled: false \ No newline at end of file diff --git a/spring-cloud-bus/spring-cloud-config-client/src/main/resources/bootstrap.properties b/spring-cloud-bus/spring-cloud-config-client/src/main/resources/bootstrap.properties deleted file mode 100644 index 7b362614ba..0000000000 --- a/spring-cloud-bus/spring-cloud-config-client/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.application.name=config-client -spring.profiles.active=development -spring.cloud.config.uri=http://localhost:8888 -spring.cloud.config.username=root -spring.cloud.config.password=s3cr3t -spring.cloud.config.fail-fast=true -management.security.enabled=false \ No newline at end of file diff --git a/spring-cloud-bus/spring-cloud-config-server/src/main/resources/application.properties b/spring-cloud-bus/spring-cloud-config-server/src/main/resources/application.properties index 6d7a945612..00ef9f0217 100644 --- a/spring-cloud-bus/spring-cloud-config-server/src/main/resources/application.properties +++ b/spring-cloud-bus/spring-cloud-config-server/src/main/resources/application.properties @@ -6,4 +6,9 @@ spring.security.user.password=s3cr3t spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest -spring.rabbitmq.password=guest \ No newline at end of file +spring.rabbitmq.password=guest + +encrypt.key-store.location=classpath:/config-server.jks +encrypt.key-store.password=my-s70r3-s3cr3t +encrypt.key-store.alias=config-server-key +encrypt.key-store.secret=my-k34-s3cr3t \ No newline at end of file diff --git a/spring-cloud-bus/spring-cloud-config-server/src/main/resources/bootstrap.properties b/spring-cloud-bus/spring-cloud-config-server/src/main/resources/bootstrap.properties deleted file mode 100644 index b0c35c72a6..0000000000 --- a/spring-cloud-bus/spring-cloud-config-server/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,4 +0,0 @@ -encrypt.key-store.location=classpath:/config-server.jks -encrypt.key-store.password=my-s70r3-s3cr3t -encrypt.key-store.alias=config-server-key -encrypt.key-store.secret=my-k34-s3cr3t \ No newline at end of file diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 65b623febd..ac810c9a77 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -17,6 +17,7 @@ + spring-cloud-load-balancer spring-cloud-config spring-cloud-eureka spring-cloud-hystrix @@ -46,6 +47,7 @@ spring-cloud-eureka-self-preservation spring-cloud-sentinel + spring-cloud-dapr @@ -79,7 +81,7 @@ - 2020.0.3 + 2021.0.0 2.2.3.RELEASE 2.2.3.RELEASE 1.4.7.RELEASE @@ -88,4 +90,4 @@ 3.1.3 - \ No newline at end of file + diff --git a/spring-cloud/spring-cloud-archaius/additional-sources-simple/pom.xml b/spring-cloud/spring-cloud-archaius/additional-sources-simple/pom.xml index 249cbe579f..6c8ed96003 100644 --- a/spring-cloud/spring-cloud-archaius/additional-sources-simple/pom.xml +++ b/spring-cloud/spring-cloud-archaius/additional-sources-simple/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-archaius/additional-sources-simple/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-archaius/additional-sources-simple/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-archaius/additional-sources-simple/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-archaius/basic-config/pom.xml b/spring-cloud/spring-cloud-archaius/basic-config/pom.xml index bdcef5b704..5e2eb47928 100644 --- a/spring-cloud/spring-cloud-archaius/basic-config/pom.xml +++ b/spring-cloud/spring-cloud-archaius/basic-config/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-archaius/basic-config/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-archaius/basic-config/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-archaius/basic-config/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-archaius/dynamodb-config/pom.xml b/spring-cloud/spring-cloud-archaius/dynamodb-config/pom.xml index aa203670e0..08c96fb1f6 100644 --- a/spring-cloud/spring-cloud-archaius/dynamodb-config/pom.xml +++ b/spring-cloud/spring-cloud-archaius/dynamodb-config/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-archaius/extra-configs/pom.xml b/spring-cloud/spring-cloud-archaius/extra-configs/pom.xml index 552fa2eb44..4113bf5bca 100644 --- a/spring-cloud/spring-cloud-archaius/extra-configs/pom.xml +++ b/spring-cloud/spring-cloud-archaius/extra-configs/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-archaius/extra-configs/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-archaius/extra-configs/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-archaius/extra-configs/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-archaius/jdbc-config/pom.xml b/spring-cloud/spring-cloud-archaius/jdbc-config/pom.xml index 9523c187e1..dcaf934849 100644 --- a/spring-cloud/spring-cloud-archaius/jdbc-config/pom.xml +++ b/spring-cloud/spring-cloud-archaius/jdbc-config/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-archaius/pom.xml b/spring-cloud/spring-cloud-archaius/pom.xml index efd912f8db..058f383ec0 100644 --- a/spring-cloud/spring-cloud-archaius/pom.xml +++ b/spring-cloud/spring-cloud-archaius/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. @@ -46,11 +45,6 @@ org.springframework.boot spring-boot-starter-test
- - org.assertj - assertj-core - test - org.junit.platform junit-platform-runner diff --git a/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml b/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml index f54373d572..bdd75d0635 100644 --- a/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml +++ b/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring.cloud spring-cloud-archaius 1.0.0-SNAPSHOT - .. @@ -46,6 +45,7 @@ 2.0.0.RELEASE 3.4.13 + 2.17.1 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-aws/pom.xml b/spring-cloud/spring-cloud-aws/pom.xml index c9cd56bea6..312e800874 100644 --- a/spring-cloud/spring-cloud-aws/pom.xml +++ b/spring-cloud/spring-cloud-aws/pom.xml @@ -10,16 +10,15 @@ Spring Cloud AWS Examples - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT - + junit junit diff --git a/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml b/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml index dc6e196325..5326e181e0 100644 --- a/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml @@ -16,4 +16,4 @@ 1.0.0-SNAPSHOT - + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-circuit-breaker/pom.xml b/spring-cloud/spring-cloud-circuit-breaker/pom.xml index ebf89d671c..0b0dafee46 100644 --- a/spring-cloud/spring-cloud-circuit-breaker/pom.xml +++ b/spring-cloud/spring-cloud-circuit-breaker/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-config/client/pom.xml b/spring-cloud/spring-cloud-config/client/pom.xml index 55c6e77a72..0f463b6d6d 100644 --- a/spring-cloud/spring-cloud-config/client/pom.xml +++ b/spring-cloud/spring-cloud-config/client/pom.xml @@ -26,17 +26,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - - diff --git a/spring-cloud/spring-cloud-config/client/src/main/resources/application.properties b/spring-cloud/spring-cloud-config/client/src/main/resources/application.properties new file mode 100644 index 0000000000..a96e6189a1 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.application.name=config-client +spring.profiles.active=development +spring.config.import=optional:configserver:http://root:s3cr3t@localhost:8888 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties deleted file mode 100644 index 5dde8baa28..0000000000 --- a/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,6 +0,0 @@ -spring.application.name=config-client -spring.profiles.active=development -spring.cloud.config.uri=http://localhost:8888 -spring.cloud.config.username=root -spring.cloud.config.password=s3cr3t -spring.cloud.config.fail-fast=true diff --git a/spring-cloud/spring-cloud-config/pom.xml b/spring-cloud/spring-cloud-config/pom.xml index 4eda3dda0a..1c8ada8a65 100644 --- a/spring-cloud/spring-cloud-config/pom.xml +++ b/spring-cloud/spring-cloud-config/pom.xml @@ -10,10 +10,9 @@ pom - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -34,7 +33,7 @@ - 2020.0.3 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-config/server/pom.xml b/spring-cloud/spring-cloud-config/server/pom.xml index 36d1b5b3aa..b41277113f 100644 --- a/spring-cloud/spring-cloud-config/server/pom.xml +++ b/spring-cloud/spring-cloud-config/server/pom.xml @@ -30,17 +30,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - -
diff --git a/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties b/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties index 18d4b3596a..366ecddf86 100644 --- a/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties +++ b/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties @@ -3,3 +3,8 @@ spring.cloud.config.server.git.uri= spring.cloud.config.server.git.clone-on-start=true spring.security.user.name=root spring.security.user.password=s3cr3t + +encrypt.keyStore.location=classpath:/config-server.jks +encrypt.keyStore.password=my-s70r3-s3cr3t +encrypt.keyStore.alias=config-server-key +encrypt.keyStore.secret=my-k34-s3cr3t diff --git a/spring-cloud/spring-cloud-config/server/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-config/server/src/main/resources/bootstrap.properties deleted file mode 100644 index f2d75f5846..0000000000 --- a/spring-cloud/spring-cloud-config/server/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,4 +0,0 @@ -encrypt.keyStore.location=classpath:/config-server.jks -encrypt.keyStore.password=my-s70r3-s3cr3t -encrypt.keyStore.alias=config-server-key -encrypt.keyStore.secret=my-k34-s3cr3t diff --git a/spring-cloud/spring-cloud-connectors-heroku/pom.xml b/spring-cloud/spring-cloud-connectors-heroku/pom.xml index 967b1b3caf..b38ede6d89 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/pom.xml +++ b/spring-cloud/spring-cloud-connectors-heroku/pom.xml @@ -9,10 +9,9 @@ spring-cloud-connectors-heroku - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -28,7 +27,7 @@ - + org.springframework.boot spring-boot-starter-cloud-connectors ${spring-boot-starter-cloud-connectors.version} @@ -57,9 +56,9 @@ - 2.2.6.RELEASE + 2.2.6.RELEASE Hoxton.SR4 42.2.10 - + \ 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 c99dd0bd5a..b561000a83 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 @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud-contract 1.0.0-SNAPSHOT - .. 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 21c11c986b..b80b86580f 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 @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud-contract 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-dapr/gateway/pom.xml b/spring-cloud/spring-cloud-dapr/gateway/pom.xml index a12ce867ce..6545c61002 100644 --- a/spring-cloud/spring-cloud-dapr/gateway/pom.xml +++ b/spring-cloud/spring-cloud-dapr/gateway/pom.xml @@ -8,10 +8,9 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 2.5.2 - + com.baeldung.spring.cloud + spring-cloud-dapr + 1.0.0-SNAPSHOT @@ -19,7 +18,7 @@ org.springframework.cloud spring-cloud-dependencies - 2020.0.3 + ${spring-cloud-dependencies.version} pom import @@ -43,8 +42,7 @@ - 11 - 11 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-dapr/gateway/src/main/java/org/example/gateway/GatewayApp.java b/spring-cloud/spring-cloud-dapr/gateway/src/main/java/com/baeldung/gateway/GatewayApp.java similarity index 90% rename from spring-cloud/spring-cloud-dapr/gateway/src/main/java/org/example/gateway/GatewayApp.java rename to spring-cloud/spring-cloud-dapr/gateway/src/main/java/com/baeldung/gateway/GatewayApp.java index 7166b5b31f..fba04f61ee 100644 --- a/spring-cloud/spring-cloud-dapr/gateway/src/main/java/org/example/gateway/GatewayApp.java +++ b/spring-cloud/spring-cloud-dapr/gateway/src/main/java/com/baeldung/gateway/GatewayApp.java @@ -1,4 +1,4 @@ -package org.example.gateway; +package com.baeldung.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-cloud/spring-cloud-dapr/greeting/pom.xml b/spring-cloud/spring-cloud-dapr/greeting/pom.xml index 2b59166cf7..22b4004cbf 100644 --- a/spring-cloud/spring-cloud-dapr/greeting/pom.xml +++ b/spring-cloud/spring-cloud-dapr/greeting/pom.xml @@ -8,10 +8,9 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 2.5.2 - + com.baeldung.spring.cloud + spring-cloud-dapr + 1.0.0-SNAPSHOT @@ -30,9 +29,4 @@ - - 11 - 11 - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingApp.java b/spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingApp.java similarity index 90% rename from spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingApp.java rename to spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingApp.java index 2feca49daa..96096c0963 100644 --- a/spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingApp.java +++ b/spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingApp.java @@ -1,4 +1,4 @@ -package org.example.hello; +package com.baeldung.hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingController.java b/spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingController.java similarity index 94% rename from spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingController.java rename to spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingController.java index 5210add4e0..d0e3c54e43 100644 --- a/spring-cloud/spring-cloud-dapr/greeting/src/main/java/org/example/hello/GreetingController.java +++ b/spring-cloud/spring-cloud-dapr/greeting/src/main/java/com/baeldung/hello/GreetingController.java @@ -1,4 +1,4 @@ -package org.example.hello; +package com.baeldung.hello; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-cloud/spring-cloud-dapr/pom.xml b/spring-cloud/spring-cloud-dapr/pom.xml index c2e9edaedc..436666b08e 100644 --- a/spring-cloud/spring-cloud-dapr/pom.xml +++ b/spring-cloud/spring-cloud-dapr/pom.xml @@ -17,4 +17,4 @@ greeting
- + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-docker/docker-message-server/pom.xml b/spring-cloud/spring-cloud-docker/docker-message-server/pom.xml index 1c8c58c762..91cd587ff3 100644 --- a/spring-cloud/spring-cloud-docker/docker-message-server/pom.xml +++ b/spring-cloud/spring-cloud-docker/docker-message-server/pom.xml @@ -23,17 +23,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - -
diff --git a/spring-cloud/spring-cloud-docker/docker-product-server/pom.xml b/spring-cloud/spring-cloud-docker/docker-product-server/pom.xml index be65a6d7d3..ba4cf63ad8 100644 --- a/spring-cloud/spring-cloud-docker/docker-product-server/pom.xml +++ b/spring-cloud/spring-cloud-docker/docker-product-server/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 docker-product-server - docker-product-server 1.0.0 + docker-product-server com.baeldung.spring.cloud @@ -23,17 +23,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest-core - - -
diff --git a/spring-cloud/spring-cloud-docker/pom.xml b/spring-cloud/spring-cloud-docker/pom.xml index 3e407df6a1..735dae2ea7 100644 --- a/spring-cloud/spring-cloud-docker/pom.xml +++ b/spring-cloud/spring-cloud-docker/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-docker - spring-cloud-docker 1.0.0-SNAPSHOT + spring-cloud-docker pom @@ -14,14 +14,14 @@ 1.0.0-SNAPSHOT - - 8 - 8 - - docker-message-server docker-product-server + + 8 + 8 + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-eureka-self-preservation/pom.xml b/spring-cloud/spring-cloud-eureka-self-preservation/pom.xml index 26353f8297..0b7da2ce4a 100644 --- a/spring-cloud/spring-cloud-eureka-self-preservation/pom.xml +++ b/spring-cloud/spring-cloud-eureka-self-preservation/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-client/pom.xml index f2670a5114..ddce6e1af6 100644 --- a/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-client/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud.eureka spring-cloud-eureka-self-preservation 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-server/pom.xml index b21e5100ef..0976481395 100644 --- a/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-server/pom.xml +++ b/spring-cloud/spring-cloud-eureka-self-preservation/spring-cloud-eureka-server/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud.eureka spring-cloud-eureka-self-preservation 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka/pom.xml b/spring-cloud/spring-cloud-eureka/pom.xml index 5cf0a74868..e5327d4530 100644 --- a/spring-cloud/spring-cloud-eureka/pom.xml +++ b/spring-cloud/spring-cloud-eureka/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml index a3c78154a2..a16059a19b 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud-eureka 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml index b51fd11e29..ca29a890dd 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud-eureka 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml index 9c8e6f3e70..7ba300289e 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud-eureka 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml index 5f5376ddc9..3dc68e2824 100644 --- a/spring-cloud/spring-cloud-functions/pom.xml +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -10,11 +10,10 @@ jar Demo project for Spring Cloud Function - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT diff --git a/spring-cloud/spring-cloud-functions/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-functions/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-functions/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/README-OAuth.md b/spring-cloud/spring-cloud-gateway/README-OAuth.md new file mode 100644 index 0000000000..c186114589 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/README-OAuth.md @@ -0,0 +1,40 @@ +# OAuth Test Setup + +In order to test the OAuth-secured gateway configurations, please follow the steps below + +## Keycloak setup + +1. Clone or download the https://github.com/Baeldung/spring-security-oauth project +2. Replace the file `oauth-rest/oauth-authorization-server/src/main/resources/baeldung-realm.json` + with the one provider here +3. Go to the oauth-rest/oauth-authorization-server folder and use maven to build the project +4. Run the Keycloack service with `mvn spring-boot:run` +5. Once Keycloak is up and running, go to `http://localhost:8083/auth/admin/master/console/#/realms/baeldung` and + log in with using `bael-admin/pass` as credentials +6. Create two test users, so that one belongs to the *Golden Customers* group and the other doesn't. + +## Quotes backend + +Use the provided maven profile: + +``` +$ mvn spring-boot:run -Pquotes-application +``` + +## Gateway as Resource Server + +Use the provided maven profile: + +``` +$ mvn spring-boot:run -Pgateway-as-resource-server +``` + +## Gateway as OAuth 2.0 Client + +Use the provided maven profile: + +``` +$ mvn spring-boot:run -Pgateway-as-oauth-client +``` + + diff --git a/spring-cloud/spring-cloud-gateway/README.md b/spring-cloud/spring-cloud-gateway/README.md index 90e81fe9a2..6b199977e3 100644 --- a/spring-cloud/spring-cloud-gateway/README.md +++ b/spring-cloud/spring-cloud-gateway/README.md @@ -3,7 +3,9 @@ This module contains articles about Spring Cloud Gateway ### Relevant Articles: + - [Exploring the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) - [Writing Custom Spring Cloud Gateway Filters](https://www.baeldung.com/spring-cloud-custom-gateway-filters) - [Spring Cloud Gateway Routing Predicate Factories](https://www.baeldung.com/spring-cloud-gateway-routing-predicate-factories) - [Spring Cloud Gateway WebFilter Factories](https://www.baeldung.com/spring-cloud-gateway-webfilter-factories) +- [Using Spring Cloud Gateway with OAuth 2.0 Patterns](https://www.baeldung.com/spring-cloud-gateway-oauth2) diff --git a/spring-cloud/spring-cloud-gateway/baeldung-realm.json b/spring-cloud/spring-cloud-gateway/baeldung-realm.json new file mode 100644 index 0000000000..4dad262568 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/baeldung-realm.json @@ -0,0 +1,2186 @@ +{ + "id": "baeldung", + "realm": "baeldung", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "2f721e46-398b-43ff-845f-3c747f1f69f5", + "name": "standard", + "description": "Standard customer", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + }, + { + "id": "b8b1cb49-c953-4cb0-acea-62b24c4b6d30", + "name": "silver", + "description": "Silver customer", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + }, + { + "id": "f44f5ba9-2393-4d2a-b581-81cf8dd7f245", + "name": "gold", + "description": "Gold customers", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + }, + { + "id": "3b6109f5-6e5a-4578-83c3-791ec3e2bf9e", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + }, + { + "id": "0dd6a8c7-d669-4941-9ea1-521980e9c53f", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + }, + { + "id": "ca962095-7f9b-49e2-a190-e391a0d4b704", + "name": "user", + "composite": false, + "clientRole": false, + "containerId": "baeldung", + "attributes": {} + } + ], + "client": { + "newClient": [], + "realm-management": [ + { + "id": "5d00243f-ceec-4b0c-995e-d86d5b8a0ae6", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "941612de-bd85-47a5-8dfa-37c270dde28c", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "5ea9810d-63cc-4277-9b32-ba8a3d3c6091", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "8b7b0dd8-350b-473e-b8cd-8acad34f1358", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "0f8e5ee8-b014-4b7c-9b69-50f46abcba5f", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "911b1489-9383-4734-b134-bf49bf992ce9", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "5d48274c-bd6b-4c26-ad54-f1a2254beac0", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "3ea43b64-316f-4693-8346-9ee78b24adaf", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "49735614-96ec-49b2-98fe-3af9bcd1a33a", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "e8f8c3cc-0ff1-4f72-a271-db6821a3cdb6", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "387418b1-4f80-4b00-b9dd-805ca041f805", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "427c27d4-521a-464b-a0df-16d7f537e8d5", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-clients", + "view-authorization", + "query-groups", + "manage-realm", + "query-clients", + "manage-clients", + "view-realm", + "manage-identity-providers", + "create-client", + "manage-users", + "view-identity-providers", + "query-users", + "query-realms", + "view-users", + "impersonation", + "manage-authorization", + "manage-events", + "view-events" + ] + } + }, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "a574cf01-03e4-4573-ab9e-276d13a1ce8d", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "c3a253a8-a1b6-4d38-9677-f728f32482ad", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "f3cb93da-273e-419a-b2f4-93f09896abcf", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "6eedf2b7-50ef-4495-a89b-54aef751b7fa", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "0332e99b-3dfc-4193-9e13-5728f8f3e6d6", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "b690cb9c-0f4a-4be5-ade0-b40443d8149d", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + }, + { + "id": "aac3def5-f193-4a6c-9065-1667a0746a8a", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", + "attributes": {} + } + ], + "security-admin-console": [], + "quotes-client": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "397b5703-4c81-48fd-a24c-a7e8177ef657", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "4b9609f0-48d1-4e71-9381-2ecec08616f9", + "attributes": {} + } + ], + "account": [ + { + "id": "8daa8096-d14e-4d1c-ad1f-83f822016aa1", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + }, + { + "id": "15f0d8be-932b-4565-8ad0-e8aa170093dd", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + }, + { + "id": "c5aa697c-bf87-47c6-bd94-9121b72420b9", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + }, + { + "id": "f0b3bbe4-aec1-4227-b9d3-2c314d612a04", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + }, + { + "id": "948269c7-a69c-4c82-a7f3-88868713dfd9", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + }, + { + "id": "aed18201-2433-4998-8fa3-0979b0b31c10", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "attributes": {} + } + ] + } + }, + "groups": [ + { + "id": "635c3314-f15f-4c02-bcb7-8739fd4c21b7", + "name": "golden_customers", + "path": "/golden_customers", + "attributes": {}, + "realmRoles": [ + "gold" + ], + "clientRoles": {}, + "subGroups": [] + }, + { + "id": "279c5ec4-0588-4884-91c1-2697ed5c9826", + "name": "silver_customers", + "path": "/silver_customers", + "attributes": {}, + "realmRoles": [ + "silver" + ], + "clientRoles": {}, + "subGroups": [] + } + ], + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/baeldung/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "manage-account", + "view-profile" + ], + "redirectUris": [ + "/realms/baeldung/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8209784b-8540-43c2-aece-241acf12ea5a", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/baeldung/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/baeldung/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "58395b96-1718-4787-8f92-74577e2bfc30", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "13d76feb-d762-4409-bb84-7a75bc395a61", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4b9609f0-48d1-4e71-9381-2ecec08616f9", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b88ce206-63d6-43b6-87c9-ea09d8c02f32", + "clientId": "newClient", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:8082/new-client/login/oauth2/code/custom", + "http://localhost:8089/", + "http://localhost:8089/auth/redirect/" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "role_list", + "profile" + ], + "optionalClientScopes": [ + "web-origins", + "address", + "read", + "phone", + "roles", + "offline_access", + "microprofile-jwt", + "write", + "email" + ] + }, + { + "id": "5898f71f-b91e-4c3f-9c86-48de0e8665c4", + "clientId": "quotes-client", + "name": "Quotes Client", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "0e082231-a70d-48e8-b8a5-fbfb743041b6", + "redirectUris": [ + "http://localhost:8082/*", + "http://localhost:8087/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.multivalued.roles": "false", + "saml.force.post.binding": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "008d32b5-ea7b-4739-89af-e90fe137bda9", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6a4bfbd0-576d-4778-af56-56f876647355", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8e358d2f-b085-4243-8e6e-c175431e5eeb", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/baeldung/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/baeldung/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "9cfca9ee-493d-4b5e-8170-2d364149de59", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "77c7e29d-1a22-4419-bbfb-4a62bb033449", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "94e1879d-b49e-4178-96e0-bf8d7f32c160", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "b3526ac1-10e2-4344-8621-9c5a0853e97a", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "d30270dc-baa6-455a-8ff6-ddccf8a78d86", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "f5b1684d-e479-4134-8578-457fa64717da", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "c658ae14-e96a-4745-b21b-2ed5c4c63f5f", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "959521bc-5ffd-465b-95f2-5b0c20d1909c", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "07b8550c-b298-4cce-9ffb-900182575b76", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "569b3d44-4ecd-4768-a58c-70ff38f4b4fe", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "a3e7b19d-df6c-437e-9eea-06fec1becb2f", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "72a070f7-4363-4c88-8153-6fd2d12b9b04", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "24b42c6d-a93c-4aa1-9a03-2a2b55954c13", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "ba8c9950-fd0b-4434-8be6-b58456d7b6d4", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0a9ddd71-309c-40f0-8ea6-a0791070c6ed", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "fbf53bbd-1ad0-4bf8-8030-50f81696d8ee", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "423be2cd-42c0-462e-9030-18f9b28ff2d3", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "53eb9006-4b81-474a-8b60-80f775d54b63", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "4d8bc82a-eaeb-499e-8eb2-0f1dcbe91699", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "d3b25485-4042-419d-afff-cfd63a76e229", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "422cfa5a-f2f4-4f36-82df-91b47ae1ea50", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "3f2863c1-d98d-45b5-b08f-af9c4d9c10f8", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "c98c063d-eee4-41a0-9130-595afd709d1f", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "8dbed80a-d672-4185-8dda-4bba2a56ec83", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "5e5c690c-93cf-489d-a054-b109eab8911b", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "3b985202-af8a-42f1-ac5f-0966a404f5d7", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "6eafd1b3-7121-4919-ad1e-039fa58acc32", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "73cba925-8c31-443f-9601-b1514e6396c1", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "c1a2eb23-25c6-4be7-a791-bbdca99c83f7", + "name": "read", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }, + { + "id": "18e141bf-dabe-4858-879c-dbc439cdead4", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "10cbe37f-0198-4d65-bc8a-bfe5ad8145d1", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "111ed87a-5fd3-4cee-96df-8dbfb88cfdc0", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "24924d8d-6071-4a93-b40f-326176cb335e", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "2f6a9bdf-3758-484c-996d-e4f93555559f", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "804d4798-d9a3-4fd3-8b28-d12142e8cb3d", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "51d49314-b511-43e0-9258-bfb873758a78", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "2b384cd0-9e85-4a87-8eeb-2b480b0587b7", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "c3e253fb-7361-47cf-9d4a-86245686fdf1", + "name": "write", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + } + ], + "defaultDefaultClientScopes": [ + "roles", + "role_list", + "web-origins", + "email", + "profile" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "84305f42-4b6d-4b0a-ac7c-53e406e3ac63", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "c7c38a95-744f-4558-a403-9cf692fe1944", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "365b2899-befe-4417-b89b-562650ec4446", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "81c32244-7921-43e9-9356-a3469259b78c", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "d09b2147-afea-4f7f-a49c-0aec7eee10de", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "41ffde1b-72a2-416f-87a7-94989e940dc0", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-property-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "76075388-2782-4656-a986-313493239a9f", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "3caaf57a-9cd7-48c1-b709-b40b887414f7", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "saml-user-property-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "d67a940a-52e4-44a5-9f69-6ffdd67a188f", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "48d40de3-6234-42e8-9449-f68f56abb54b", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "52ea1c5d-2a30-459f-b66a-249f298b32f8", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "b35b726e-c1cc-4a31-8670-8c858c088498", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Handle Existing Account - Alternatives - 0", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "b7cb4b8c-0064-4c6b-95ee-d7f50011bae7", + "alias": "Handle Existing Account - Alternatives - 0", + "description": "Subflow of Handle Existing Account with alternative executions", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2576bf21-a516-4e22-8ed8-8a1a3d35c06a", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication - auth-otp-form - Conditional", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "867b0355-c2b0-4f4e-b535-09406e2bc086", + "alias": "Verify Existing Account by Re-authentication - auth-otp-form - Conditional", + "description": "Flow to determine if the auth-otp-form authenticator should be used or not.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "52e45a6a-292f-4a34-9c02-7f97d9997a9c", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "ef818d24-fb06-418a-a093-16239068cb58", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "f7864004-be4b-40f2-8534-454981f09f98", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "direct grant - direct-grant-validate-otp - Conditional", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "233225f2-78b0-4756-9568-a775ea7cc975", + "alias": "direct grant - direct-grant-validate-otp - Conditional", + "description": "Flow to determine if the direct-grant-validate-otp authenticator should be used or not.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "2787939c-3312-4d56-9d61-22a71947e154", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c80ca473-6e65-4140-a9d1-035414546bfb", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "first broker login - Alternatives - 0", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "700a71e1-f176-432e-9e70-ccb06d539730", + "alias": "first broker login - Alternatives - 0", + "description": "Subflow of first broker login with alternative executions", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "13cd2ee9-8ebb-4651-8a9d-535d4020d889", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "forms - auth-otp-form - Conditional", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "80067ebf-72b9-4ba5-abc3-161dfdd53938", + "alias": "forms - auth-otp-form - Conditional", + "description": "Flow to determine if the auth-otp-form authenticator should be used or not.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "269354b1-7dd7-46ff-8a69-084cd2c7be80", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c5fa64a0-e784-490f-8879-0e8a209e3636", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "bc48f897-4d16-49a8-be70-183c7867e20a", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "fddaba41-87b1-40d1-b147-f062c38e39ad", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "reset credentials - reset-otp - Conditional", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6b9fa295-1eb4-48b0-a286-b17ebd6be7e1", + "alias": "reset credentials - reset-otp - Conditional", + "description": "Flow to determine if the reset-otp authenticator should be used or not.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c890d4c4-e4e2-4618-b69d-8d30f8278965", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "2b02fbe4-e05e-4238-bb0e-04da7d4efd4e", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "07dd933b-ce95-4a7c-bd81-3efa24f9558c", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0" + }, + "keycloakVersion": "11.0.2", + "userManagedAccessAllowed": false +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/pom.xml b/spring-cloud/spring-cloud-gateway/pom.xml index eaa0d12cfd..a352bbd4e4 100644 --- a/spring-cloud/spring-cloud-gateway/pom.xml +++ b/spring-cloud/spring-cloud-gateway/pom.xml @@ -11,7 +11,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. @@ -84,23 +83,115 @@ org.springframework.boot spring-boot-devtools + + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + + org.springframework.boot + spring-boot-starter-oauth2-client + +
+ + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + org.springframework.boot spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + - Hoxton.SR3 - 2.2.6.RELEASE + + 6.0.2.Final 0.7.2 - 5.5.2 + 9.19 + - + + + + quotes-application + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.springcloudgateway.oauth.backend.QuotesApplication + + + + + + + gateway-as-resource-server + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.springcloudgateway.oauth.server.ResourceServerGatewayApplication + -Dspring.profiles.active=resource-server + + + + + + + gateway-as-oauth-client + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.springcloudgateway.oauth.server.ResourceServerGatewayApplication + -Dspring.profiles.active=oauth-client + + + + + + + + gateway-url-rewrite + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.springcloudgateway.rewrite.URLRewriteGatewayApplication + -Dspring.profiles.active=url-rewrite + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/config/CustomPredicatesConfig.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/config/CustomPredicatesConfig.java index 0e88b29bcf..ea58eb7e46 100644 --- a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/config/CustomPredicatesConfig.java +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/config/CustomPredicatesConfig.java @@ -1,6 +1,5 @@ package com.baeldung.springcloudgateway.custompredicates.config; -import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; @@ -24,14 +23,20 @@ public class CustomPredicatesConfig { public RouteLocator routes(RouteLocatorBuilder builder, GoldenCustomerRoutePredicateFactory gf ) { return builder.routes() - .route("dsl_golden_route", r -> r.path("/dsl_api/**") - .filters(f -> f.stripPrefix(1)) - .uri("https://httpbin.org") - .predicate(gf.apply(new Config(true, "customerId")))) - .route("dsl_common_route", r -> r.path("/dsl_api/**") - .filters(f -> f.stripPrefix(1)) - .uri("https://httpbin.org") - .predicate(gf.apply(new Config(false, "customerId")))) + .route("dsl_golden_route", r -> + r.predicate(gf.apply(new Config(true, "customerId"))) + .and() + .path("/dsl_api/**") + .filters(f -> f.stripPrefix(1)) + .uri("https://httpbin.org") + ) + .route("dsl_common_route", r -> + r.predicate(gf.apply(new Config(false, "customerId"))) + .and() + .path("/dsl_api/**") + .filters(f -> f.stripPrefix(1)) + .uri("https://httpbin.org") + ) .build(); } diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/QuotesApplication.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/QuotesApplication.java new file mode 100644 index 0000000000..96daf8a73d --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/QuotesApplication.java @@ -0,0 +1,44 @@ +/** + * + */ +package com.baeldung.springcloudgateway.oauth.backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.PropertySource; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.oauth2.server.resource.introspection.NimbusReactiveOpaqueTokenIntrospector; +import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; + +import com.baeldung.springcloudgateway.oauth.shared.KeycloakReactiveTokenInstrospector; + +/** + * @author Philippe + * + */ +@SpringBootApplication +@PropertySource("classpath:quotes-application.properties") +@EnableWebFluxSecurity +public class QuotesApplication { + + public static void main(String[] args) { + SpringApplication.run(QuotesApplication.class); + } + + + @Bean + public ReactiveOpaqueTokenIntrospector keycloakIntrospector(OAuth2ResourceServerProperties props) { + + NimbusReactiveOpaqueTokenIntrospector delegate = new NimbusReactiveOpaqueTokenIntrospector( + props.getOpaquetoken().getIntrospectionUri(), + props.getOpaquetoken().getClientId(), + props.getOpaquetoken().getClientSecret()); + + return new KeycloakReactiveTokenInstrospector(delegate); + } + + +} + diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/domain/Quote.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/domain/Quote.java new file mode 100644 index 0000000000..042cfa63fa --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/domain/Quote.java @@ -0,0 +1,35 @@ +package com.baeldung.springcloudgateway.oauth.backend.domain; + + +public class Quote { + + private String symbol; + private double price; + + /** + * @return the symbol + */ + public String getSymbol() { + return symbol; + } + /** + * @param symbol the symbol to set + */ + public void setSymbol(String symbol) { + this.symbol = symbol; + } + /** + * @return the price + */ + public double getPrice() { + return price; + } + /** + * @param price the price to set + */ + public void setPrice(double price) { + this.price = price; + } + + +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java new file mode 100644 index 0000000000..6d3721166c --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java @@ -0,0 +1,34 @@ +package com.baeldung.springcloudgateway.oauth.backend.web; + +import javax.annotation.PostConstruct; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.springcloudgateway.oauth.backend.domain.Quote; + +import reactor.core.publisher.Mono; + +@RestController +public class QuoteApi { + private static final GrantedAuthority GOLD_CUSTOMER = new SimpleGrantedAuthority("gold"); + + @GetMapping("/quotes/{symbol}") + public Mono getQuote(@PathVariable("symbol") String symbol, BearerTokenAuthentication auth ) { + + Quote q = new Quote(); + q.setSymbol(symbol); + + if ( auth.getAuthorities().contains(GOLD_CUSTOMER)) { + q.setPrice(10.0); + } + else { + q.setPrice(12.0); + } + return Mono.just(q); + } +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/server/ResourceServerGatewayApplication.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/server/ResourceServerGatewayApplication.java new file mode 100644 index 0000000000..1b85867f3b --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/server/ResourceServerGatewayApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.springcloudgateway.oauth.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; + +@SpringBootApplication +@EnableWebFluxSecurity +public class ResourceServerGatewayApplication { + public static void main(String[] args) { + SpringApplication.run(ResourceServerGatewayApplication.class,args); + } +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/shared/KeycloakReactiveTokenInstrospector.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/shared/KeycloakReactiveTokenInstrospector.java new file mode 100644 index 0000000000..e834e6934d --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/shared/KeycloakReactiveTokenInstrospector.java @@ -0,0 +1,65 @@ +/** + * + */ +package com.baeldung.springcloudgateway.oauth.shared; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal; +import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; +import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; + +import reactor.core.publisher.Mono; + +/** + * Custom ReactiveTokenIntrospector to map realm roles into Spring GrantedAuthorities + * + */ +public class KeycloakReactiveTokenInstrospector implements ReactiveOpaqueTokenIntrospector { + + private final ReactiveOpaqueTokenIntrospector delegate; + + public KeycloakReactiveTokenInstrospector(ReactiveOpaqueTokenIntrospector delegate) { + this.delegate = delegate; + } + + @Override + public Mono introspect(String token) { + + return delegate.introspect(token) + .map( this::mapPrincipal); + } + + protected OAuth2AuthenticatedPrincipal mapPrincipal(OAuth2AuthenticatedPrincipal principal) { + + return new DefaultOAuth2AuthenticatedPrincipal( + principal.getName(), + principal.getAttributes(), + extractAuthorities(principal)); + } + + protected Collection extractAuthorities(OAuth2AuthenticatedPrincipal principal) { + + // + Map> realm_access = principal.getAttribute("realm_access"); + List roles = realm_access.getOrDefault("roles", Collections.emptyList()); + List rolesAuthorities = roles.stream() + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + + Set allAuthorities = new HashSet<>(); + allAuthorities.addAll(principal.getAuthorities()); + allAuthorities.addAll(rolesAuthorities); + + return allAuthorities; + } + +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java new file mode 100644 index 0000000000..46541b4826 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java @@ -0,0 +1,25 @@ +/** + * + */ +package com.baeldung.springcloudgateway.rewrite; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.gateway.filter.GatewayFilter; + +import reactor.core.publisher.Mono; + +/** + * @author Baeldung + * + */ +@SpringBootApplication +public class URLRewriteGatewayApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder(URLRewriteGatewayApplication.class) + .profiles("url-rewrite") + .run(args); + } + +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java new file mode 100644 index 0000000000..29d40d7021 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java @@ -0,0 +1,43 @@ +package com.baeldung.springcloudgateway.rewrite.routes; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.http.server.reactive.ServerHttpRequest; + +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; + +import java.util.Random; + +@Configuration +@Profile("url-rewrite") +public class DynamicRewriteRoute { + + @Value("${rewrite.backend.uri}") + private String backendUri; + private static Random rnd = new Random(); + + @Bean + public RouteLocator dynamicZipCodeRoute(RouteLocatorBuilder builder) { + return builder.routes() + .route("dynamicRewrite", r -> + r.path("/v2/zip/**") + .filters(f -> f.filter((exchange, chain) -> { + ServerHttpRequest req = exchange.getRequest(); + addOriginalRequestUrl(exchange, req.getURI()); + String path = req.getURI().getRawPath(); + String newPath = path.replaceAll( + "/v2/zip/(?.*)", + "/api/zip/${zipcode}-" + String.format("%03d", rnd.nextInt(1000))); + ServerHttpRequest request = req.mutate().path(newPath).build(); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); + return chain.filter(exchange.mutate().request(request).build()); + })) + .uri(backendUri)) + .build(); + } +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java index 852e5cadba..9e212cc4bf 100644 --- a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java @@ -8,7 +8,7 @@ public class WebFilterGatewayApplication { public static void main(String[] args) { new SpringApplicationBuilder(WebFilterGatewayApplication.class) - .profiles("webfilters") + .profiles("url-rewrite") .run(args); } diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/application-nosecurity.yml b/spring-cloud/spring-cloud-gateway/src/main/resources/application-nosecurity.yml new file mode 100644 index 0000000000..40a52ded0f --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/application-nosecurity.yml @@ -0,0 +1,8 @@ +# Enable this profile to disable security +spring: + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration + - org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration + - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration + - org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/application-oauth-client.yml b/spring-cloud/spring-cloud-gateway/src/main/resources/application-oauth-client.yml new file mode 100644 index 0000000000..b097c54eb1 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/application-oauth-client.yml @@ -0,0 +1,26 @@ +server: + port: 8087 +spring: + cloud: + gateway: + redis: + enabled: false + routes: + - id: quotes + uri: http://localhost:8085 + predicates: + - Path=/quotes/** + filters: - TokenRelay= + security: + oauth2: + client: provider: keycloak: + issuer-uri: http://localhost:8083/auth/realms/baeldung + registration: quotes-client: + provider: keycloak + client-id: quotes-client + client-secret: 0e082231-a70d-48e8-b8a5-fbfb743041b6 + scope: - email + - profile + - roles + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/application-resource-server.yml b/spring-cloud/spring-cloud-gateway/src/main/resources/application-resource-server.yml new file mode 100644 index 0000000000..14f713a04a --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/application-resource-server.yml @@ -0,0 +1,19 @@ +server: + port: 8086 +spring: + security: + oauth2: + resourceserver: + opaquetoken: + introspection-uri: http://localhost:8083/auth/realms/baeldung/protocol/openid-connect/token/introspect + client-id: quotes-client + client-secret: 0e082231-a70d-48e8-b8a5-fbfb743041b6 + cloud: + gateway: + redis: + enabled: false + routes: + - id: quotes + uri: http://localhost:8085 + predicates: + - Path=/quotes/** diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/application-url-rewrite.yml b/spring-cloud/spring-cloud-gateway/src/main/resources/application-url-rewrite.yml new file mode 100644 index 0000000000..b2656151db --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/application-url-rewrite.yml @@ -0,0 +1,11 @@ +spring: + cloud: + gateway: + routes: + - id: rewrite_v1 + uri: ${rewrite.backend.uri:http://example.com} + predicates: + - Path=/v1/customer/** + filters: + - RewritePath=/v1/customer/(?.*),/api/$\{segment} + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/quotes-application.properties b/spring-cloud/spring-cloud-gateway/src/main/resources/quotes-application.properties new file mode 100644 index 0000000000..48e8999b1b --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/quotes-application.properties @@ -0,0 +1,12 @@ +server.port=8085 +# Disable gateway & redis as we don't need them in this application +spring.cloud.gateway.enabled=false +spring.cloud.gateway.redis.enabled=false + +# Resource server settings +spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=http://localhost:8083/auth/realms/baeldung/protocol/openid-connect/token/introspect +spring.security.oauth2.resourceserver.opaquetoken.client-id=quotes-client +spring.security.oauth2.resourceserver.opaquetoken.client-secret=0e082231-a70d-48e8-b8a5-fbfb743041b6 + + + diff --git a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java index 6b2a432d20..f4b3d0f00d 100644 --- a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java +++ b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java @@ -2,12 +2,14 @@ package com.baeldung.springcloudgateway.customfilters.secondservice; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.test.web.reactive.server.WebTestClient; import com.baeldung.springcloudgateway.customfilters.secondservice.web.SecondServiceRestController; -@WebFluxTest(SecondServiceRestController.class) +@WebFluxTest(controllers = SecondServiceRestController.class, + excludeAutoConfiguration = ReactiveSecurityAutoConfiguration.class) public class SecondServiceIntegrationTest { @Autowired diff --git a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java index bfb3f23f0d..9990cd003c 100644 --- a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java +++ b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java @@ -2,13 +2,15 @@ package com.baeldung.springcloudgateway.customfilters.service; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.http.HttpHeaders; import org.springframework.test.web.reactive.server.WebTestClient; import com.baeldung.springcloudgateway.customfilters.service.web.ServiceRestController; -@WebFluxTest(ServiceRestController.class) +@WebFluxTest(controllers = ServiceRestController.class, + excludeAutoConfiguration = ReactiveSecurityAutoConfiguration.class) public class ServiceIntegrationTest { @Autowired diff --git a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java new file mode 100644 index 0000000000..41fe37045c --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java @@ -0,0 +1,109 @@ +package com.baeldung.springcloudgateway.rewrite; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.OutputStream; +import java.net.InetSocketAddress; + +import org.junit.AfterClass; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.reactive.server.WebTestClient; + +import com.sun.net.httpserver.HttpServer; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@ActiveProfiles({ "nosecurity", "url-rewrite" }) +class URLRewriteGatewayApplicationLiveTest { + + // NOTE for Eclipse users: By default, Eclipse will complain about com.sun.** classes. + // To solve this issue, follow instructions available at the : + // https://stackoverflow.com/questions/13155734/eclipse-cant-recognize-com-sun-net-httpserver-httpserver-package + private static HttpServer mockServer; + private static Logger log = LoggerFactory.getLogger(URLRewriteGatewayApplicationLiveTest.class); + + // Create a running HttpServer that echoes back the request URL. + private static HttpServer startTestServer() { + + try { + log.info("[I26] Starting mock server"); + mockServer = HttpServer.create(); + mockServer.bind(new InetSocketAddress(0), 0); + mockServer.createContext("/api", (xchg) -> { + String uri = xchg.getRequestURI() + .toString(); + log.info("[I23] Backend called: uri={}", uri); + xchg.getResponseHeaders() + .add("Content-Type", "text/plain"); + xchg.sendResponseHeaders(200, 0); + OutputStream os = xchg.getResponseBody(); + os.write(uri.getBytes()); + os.flush(); + os.close(); + }); + + mockServer.start(); + InetSocketAddress localAddr = mockServer.getAddress(); + log.info("[I36] mock server started: local address={}", localAddr); + + return mockServer; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + } + + // TIP: https://www.baeldung.com/spring-dynamicpropertysource + @DynamicPropertySource + static void registerBackendServer(DynamicPropertyRegistry registry) { + registry.add("rewrite.backend.uri", () -> { + HttpServer s = startTestServer(); + return "http://localhost:" + s.getAddress().getPort(); + }); + } + + @AfterClass + public static void stopMockBackend() throws Exception { + log.info("[I40] Shutdown mock http server"); + mockServer.stop(5); + } + + @LocalServerPort + private int localPort; + + @Test + void testWhenApiCall_thenRewriteSuccess(@Autowired WebTestClient webClient) { + webClient.get() + .uri("http://localhost:" + localPort + "/v1/customer/customer1") + .exchange() + .expectBody() + .consumeWith((result) -> { + String body = new String(result.getResponseBody()); + log.info("[I99] body={}", body); + assertEquals("/api/customer1", body); + }); + } + + @Test + void testWhenDslCall_thenRewriteSuccess(@Autowired WebTestClient webClient) { + webClient.get() + .uri("http://localhost:" + localPort + "/v2/zip/123456") + .exchange() + .expectBody() + .consumeWith((result) -> { + String body = new String(result.getResponseBody()); + log.info("[I99] body={}", body); + assertTrue(body.matches("/api/zip/123456-\\d{3}")); + }); + } + +} diff --git a/spring-cloud/spring-cloud-gateway/src/test/postman/OAuth_Gateway.postman_collection.json b/spring-cloud/spring-cloud-gateway/src/test/postman/OAuth_Gateway.postman_collection.json new file mode 100644 index 0000000000..ac920a271b --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/test/postman/OAuth_Gateway.postman_collection.json @@ -0,0 +1,203 @@ +{ + "info": { + "_postman_id": "b3d00e23-c2cd-40ce-a90b-673efb25e5c0", + "name": "Baeldung - OAuth", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();\r", + "pm.environment.set(\"access_token\", jsonData.access_token);\r", + "pm.environment.set(\"refresh_token\", jsonData.refresh_token);\r", + "pm.environment.set(\"backend_token\", \"Bearer \" + jsonData.access_token);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "client_id", + "value": "{{client_id}}", + "type": "text" + }, + { + "key": "client_secret", + "value": "{{client_secret}}", + "type": "text" + }, + { + "key": "grant_type", + "value": "password", + "type": "text" + }, + { + "key": "scope", + "value": "email roles profile", + "type": "text" + }, + { + "key": "username", + "value": "maxwell.smart", + "type": "text" + }, + { + "key": "password", + "value": "1234", + "type": "text" + } + ] + }, + "url": { + "raw": "{{keycloack_base}}/token", + "host": [ + "{{keycloack_base}}" + ], + "path": [ + "token" + ] + } + }, + "response": [] + }, + { + "name": "Quote", + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "accept": true + } + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "http://localhost:8085/quotes/:symbol", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8085", + "path": [ + "quotes", + ":symbol" + ], + "variable": [ + { + "key": "symbol", + "value": "IBM" + } + ] + } + }, + "response": [] + }, + { + "name": "Quote via Gateway", + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "accept": true + } + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "http://localhost:8086/quotes/:symbol", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8086", + "path": [ + "quotes", + ":symbol" + ], + "variable": [ + { + "key": "symbol", + "value": "IBM" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "keycloack_base", + "value": "http://localhost:8083/auth/realms/baeldung/protocol/openid-connect" + }, + { + "key": "client_id", + "value": "quotes-client" + }, + { + "key": "client_secret", + "value": "56be94c8-b20a-4374-899c-e39cb022d3f8" + } + ] +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml index ea46ae3293..b57ef7f7d3 100644 --- a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-hystrix 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-hystrix/pom.xml b/spring-cloud/spring-cloud-hystrix/pom.xml index 4fa0a31d62..48216827c8 100644 --- a/spring-cloud/spring-cloud-hystrix/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml index 73a0859785..741457529c 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-hystrix 1.0.0-SNAPSHOT - ../ diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml index 4843c592c9..8c72b34f87 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-hystrix 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml index e916f2bc3e..cedd46dfef 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 client-service - client-service 1.0-SNAPSHOT + client-service com.baeldung.spring.cloud diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/pom.xml index 725aa9cd3d..928f401405 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 liveness-example - liveness-example 1.0-SNAPSHOT + liveness-example com.baeldung.spring.cloud diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/pom.xml index 410717f5e0..b86c13d2f0 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 readiness-example - readiness-example 1.0-SNAPSHOT + readiness-example com.baeldung.spring.cloud diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes/pom.xml b/spring-cloud/spring-cloud-kubernetes/pom.xml index d8894eb36f..c41c500a1b 100644 --- a/spring-cloud/spring-cloud-kubernetes/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/pom.xml @@ -10,10 +10,9 @@ pom - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -38,7 +37,7 @@ - 2020.0.3 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-load-balancer/README.md b/spring-cloud/spring-cloud-load-balancer/README.md new file mode 100644 index 0000000000..76a839e3f0 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Introduction to Spring Cloud Load Balancer](https://www.baeldung.com/spring-cloud-load-balancer) diff --git a/spring-cloud/spring-cloud-load-balancer/pom.xml b/spring-cloud/spring-cloud-load-balancer/pom.xml new file mode 100644 index 0000000000..9c650565ed --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + spring-cloud-loadbalancer + 1.0.0-SNAPSHOT + spring-cloud-loadbalancer + pom + Spring Cloud Load Balancer Demo Server and Client + + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + + + + spring-cloud-loadbalancer-server + spring-cloud-loadbalancer-client + + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + + + 2.6.1 + 2021.0.0 + + + diff --git a/guest/slf4j/guide/slf4j-log4j/.gitignore b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.gitignore similarity index 60% rename from guest/slf4j/guide/slf4j-log4j/.gitignore rename to spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.gitignore index 82eca336e3..549e00a2a9 100644 --- a/guest/slf4j/guide/slf4j-log4j/.gitignore +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.gitignore @@ -1,5 +1,8 @@ -/target/ +HELP.md +target/ !.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ ### STS ### .apt_generated @@ -18,8 +21,13 @@ ### NetBeans ### /nbproject/private/ -/build/ /nbbuild/ /dist/ /nbdist/ -/.nb-gradle/ \ No newline at end of file +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..e76d1f3241 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.jar similarity index 64% rename from spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar rename to spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.jar index 9cc84ea9b4..2cc7d4a55c 100644 Binary files a/spring-boot-modules/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar and b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.properties b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..a9f1ef87bb --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw new file mode 100755 index 0000000000..a16b5431b4 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw.cmd b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw.cmd new file mode 100644 index 0000000000..c8d43372c9 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/pom.xml b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/pom.xml new file mode 100644 index 0000000000..fc6e2854aa --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-loadbalancer + 1.0.0-SNAPSHOT + + + com.baeldung.springcloud.loadbalancer + spring-cloud-loadbalancer-client + 0.0.1-SNAPSHOT + spring-cloud-loadbalancer-client + Spring Cloud Load Balancer Demo - Client + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/java/com/baeldung/spring/cloud/loadbalancer/client/ClientApplication.java b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/java/com/baeldung/spring/cloud/loadbalancer/client/ClientApplication.java new file mode 100644 index 0000000000..e9f1f7ad04 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/java/com/baeldung/spring/cloud/loadbalancer/client/ClientApplication.java @@ -0,0 +1,76 @@ +package com.baeldung.spring.cloud.loadbalancer.client; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; + +import java.util.Arrays; +import java.util.List; + +@SpringBootApplication +public class ClientApplication { + public static void main(String[] args) { + + ConfigurableApplicationContext ctx = new SpringApplicationBuilder(ClientApplication.class) + .web(WebApplicationType.NONE) + .run(args); + + WebClient loadBalancedClient = ctx.getBean(WebClient.Builder.class).build(); + + for(int i = 1; i <= 10; i++) { + String response = + loadBalancedClient.get().uri("http://example-service/hello") + .retrieve().toEntity(String.class) + .block().getBody(); + System.out.println(response); + } + } +} + +@Configuration +class DemoServerInstanceConfiguration { + @Bean + ServiceInstanceListSupplier serviceInstanceListSupplier() { + return new DemoInstanceSupplier("example-service"); + } +} + +@Configuration +@LoadBalancerClient(name = "example-service", configuration = DemoServerInstanceConfiguration.class) +class WebClientConfig { + @LoadBalanced + @Bean + WebClient.Builder webClientBuilder() { + return WebClient.builder(); + } +} + +class DemoInstanceSupplier implements ServiceInstanceListSupplier { + private final String serviceId; + + public DemoInstanceSupplier(String serviceId) { + this.serviceId = serviceId; + } + + @Override + public String getServiceId() { + return serviceId; + } + + @Override + public Flux> get() { + return Flux.just(Arrays + .asList(new DefaultServiceInstance(serviceId + "1", serviceId, "localhost", 8080, false), + new DefaultServiceInstance(serviceId + "2", serviceId, "localhost", 8081, false))); + } +} diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/resources/application.properties b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-client/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/guest/slf4j/guide/slf4j-log4j2/.gitignore b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.gitignore similarity index 60% rename from guest/slf4j/guide/slf4j-log4j2/.gitignore rename to spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.gitignore index 82eca336e3..549e00a2a9 100644 --- a/guest/slf4j/guide/slf4j-log4j2/.gitignore +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.gitignore @@ -1,5 +1,8 @@ -/target/ +HELP.md +target/ !.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ ### STS ### .apt_generated @@ -18,8 +21,13 @@ ### NetBeans ### /nbproject/private/ -/build/ /nbbuild/ /dist/ /nbdist/ -/.nb-gradle/ \ No newline at end of file +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..e76d1f3241 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.jar b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000..2cc7d4a55c Binary files /dev/null and b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.properties b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..a9f1ef87bb --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw new file mode 100755 index 0000000000..a16b5431b4 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw.cmd b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw.cmd new file mode 100644 index 0000000000..c8d43372c9 --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/pom.xml b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/pom.xml new file mode 100644 index 0000000000..139996994d --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-loadbalancer + 1.0.0-SNAPSHOT + + + com.baeldung.spring.cloud.loadbalancer + spring-cloud-loadbalancer-server + 0.0.1-SNAPSHOT + spring-cloud-loadbalancer-server + Spring Cloud Load Balancer Demo - Server + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/java/com/baeldung/spring/cloud/loadbalancer/server/ServerApplication.java b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/java/com/baeldung/spring/cloud/loadbalancer/server/ServerApplication.java new file mode 100644 index 0000000000..17e7c1b50a --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/java/com/baeldung/spring/cloud/loadbalancer/server/ServerApplication.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.cloud.loadbalancer.server; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@RestController +public class ServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class, args); + } + + @Value("${server.instance.id}") + String instanceId; + + @GetMapping("/hello") + public String hello() + { + return String.format("Hello from instance %s", instanceId); + } +} diff --git a/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/resources/application.properties b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/resources/application.properties new file mode 100644 index 0000000000..4148ed304d --- /dev/null +++ b/spring-cloud/spring-cloud-load-balancer/spring-cloud-loadbalancer-server/src/main/resources/application.properties @@ -0,0 +1 @@ +server.instance.id=1 diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml index 1cb618c7e1..480663eb1c 100644 --- a/spring-cloud/spring-cloud-openfeign/pom.xml +++ b/spring-cloud/spring-cloud-openfeign/pom.xml @@ -5,7 +5,6 @@ 4.0.0 com.baeldung.cloud spring-cloud-openfeign - 0.0.1-SNAPSHOT spring-cloud-openfeign OpenFeign project for Spring Boot @@ -49,7 +48,14 @@ io.github.openfeign.form feign-form-spring - 3.8.0 + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-oauth2-client org.springframework.boot @@ -59,7 +65,7 @@ - Hoxton.SR6 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java new file mode 100644 index 0000000000..91932fb7d8 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java @@ -0,0 +1,16 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.model.Payment; +import com.baeldung.cloud.openfeign.oauthfeign.OAuthFeignConfig; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@FeignClient(name = "payment-client", url = "http://localhost:8081/resource-server-jwt", configuration = OAuthFeignConfig.class) +public interface PaymentClient { + + @RequestMapping(value = "/payments", method = RequestMethod.GET) + List getPayments(); +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java new file mode 100644 index 0000000000..97c9437ce1 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java @@ -0,0 +1,24 @@ +package com.baeldung.cloud.openfeign.controller; + +import com.baeldung.cloud.openfeign.client.PaymentClient; +import com.baeldung.cloud.openfeign.model.Payment; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class PaymentController { + + private final PaymentClient paymentClient; + + public PaymentController(PaymentClient paymentClient) { + this.paymentClient = paymentClient; + } + + @GetMapping("/payments") + public List getPayments() { + List payments = paymentClient.getPayments(); + return payments; + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java new file mode 100644 index 0000000000..c6d45bedbd --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java @@ -0,0 +1,23 @@ +package com.baeldung.cloud.openfeign.model; + +public class Payment { + + private String id; + private double amount; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public double getAmount() { + return amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java new file mode 100644 index 0000000000..af60c3849b --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java @@ -0,0 +1,19 @@ +package com.baeldung.cloud.openfeign.oauthfeign; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf() + .disable() + .oauth2Client(); + http + .authorizeRequests().anyRequest().permitAll(); + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java new file mode 100644 index 0000000000..5e958a93de --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java @@ -0,0 +1,85 @@ +package com.baeldung.cloud.openfeign.oauthfeign; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.registration.ClientRegistration; + +import java.util.Collection; +import java.util.Collections; + +import static java.util.Objects.isNull; + +public class OAuthClientCredentialsFeignManager { + + private static final Logger logger = LoggerFactory.getLogger(OAuthClientCredentialsFeignManager.class); + + private final OAuth2AuthorizedClientManager manager; + private final Authentication principal; + private final ClientRegistration clientRegistration; + + public OAuthClientCredentialsFeignManager(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration) { + this.manager = manager; + this.clientRegistration = clientRegistration; + this.principal = createPrincipal(); + } + + private Authentication createPrincipal() { + return new Authentication() { + @Override + public Collection getAuthorities() { + return Collections.emptySet(); + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public Object getPrincipal() { + return this; + } + + @Override + public boolean isAuthenticated() { + return false; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + } + + @Override + public String getName() { + return clientRegistration.getClientId(); + } + }; + } + + public String getAccessToken() { + try { + OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(clientRegistration.getRegistrationId()) + .principal(principal) + .build(); + OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest); + if (isNull(client)) { + throw new IllegalStateException("client credentials flow on " + clientRegistration.getRegistrationId() + " failed, client is null"); + } + return client.getAccessToken().getTokenValue(); + } catch (Exception exp) { + logger.error("client credentials error " + exp.getMessage()); + } + return null; + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java new file mode 100644 index 0000000000..70ca45d86e --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java @@ -0,0 +1,46 @@ +package com.baeldung.cloud.openfeign.oauthfeign; + +import feign.RequestInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.*; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; + +@Configuration +public class OAuthFeignConfig { + + public static final String CLIENT_REGISTRATION_ID = "keycloak"; + + private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService; + private final ClientRegistrationRepository clientRegistrationRepository; + + public OAuthFeignConfig(OAuth2AuthorizedClientService oAuth2AuthorizedClientService, + ClientRegistrationRepository clientRegistrationRepository) { + this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService; + this.clientRegistrationRepository = clientRegistrationRepository; + } + + @Bean + public RequestInterceptor requestInterceptor() { + ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(CLIENT_REGISTRATION_ID); + OAuthClientCredentialsFeignManager clientCredentialsFeignManager = + new OAuthClientCredentialsFeignManager(authorizedClientManager(), clientRegistration); + return requestTemplate -> { + requestTemplate.header("Authorization", "Bearer " + clientCredentialsFeignManager.getAccessToken()); + }; + } + + @Bean + OAuth2AuthorizedClientManager authorizedClientManager() { + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials() + .build(); + + AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = + new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + return authorizedClientManager; + } + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties index 41bbbde2c3..7188b74c9b 100644 --- a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties +++ b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties @@ -1,3 +1,10 @@ +server.port=8085 +spring.main.allow-bean-definition-overriding=true spring.application.name= openfeign logging.level.com.baeldung.cloud.openfeign.client: DEBUG feign.hystrix.enabled=true + +spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials +spring.security.oauth2.client.registration.keycloak.client-id=payment-app +spring.security.oauth2.client.registration.keycloak.client-secret=863e9de4-33d4-4471-b35e-f8d2434385bb +spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8083/auth/realms/master/protocol/openid-connect/token diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java index 72d2baa5d7..8ae6883519 100644 --- a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java +++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java @@ -15,7 +15,7 @@ import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) @SpringBootTest -public class OpenfeignUnitTest { +public class OpenfeignManualTest { @Autowired private JSONPlaceHolderService jsonPlaceHolderService; diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java new file mode 100644 index 0000000000..0372728515 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.cloud.openfeign; + +import com.baeldung.cloud.openfeign.client.PaymentClient; +import com.baeldung.cloud.openfeign.model.Payment; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static org.junit.Assert.assertFalse; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class PaymentClientUnitTest { + + @Autowired + private PaymentClient paymentClient; + + @Test + public void whenGetPayment_thenListPayments() { + + List payments = paymentClient.getPayments(); + + assertFalse(payments.isEmpty()); + } + +} diff --git a/spring-cloud/spring-cloud-ribbon-client/pom.xml b/spring-cloud/spring-cloud-ribbon-client/pom.xml index 2c2bce4bcd..3f7d8e9284 100644 --- a/spring-cloud/spring-cloud-ribbon-client/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-client/pom.xml @@ -9,10 +9,9 @@ Introduction to Spring Cloud Rest Client with Netflix Ribbon - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -47,7 +46,7 @@ - 2020.0.3 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RestTemplateConfiguration.java b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RestTemplateConfiguration.java new file mode 100644 index 0000000000..c69168fc74 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RestTemplateConfiguration.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.cloud.ribbon.client; + +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfiguration { + + @LoadBalanced + @Bean + RestTemplate getRestTemplate() { + return new RestTemplate(); + } +} diff --git a/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java index 6105e2c489..b7b92d114d 100644 --- a/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java +++ b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java @@ -3,9 +3,7 @@ package com.baeldung.spring.cloud.ribbon.client; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.ribbon.RibbonClient; -import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @@ -15,19 +13,12 @@ import org.springframework.web.client.RestTemplate; @RibbonClient(name = "ping-a-server", configuration = RibbonConfiguration.class) public class ServerLocationApp { - @LoadBalanced - @Bean - RestTemplate getRestTemplate() { - return new RestTemplate(); - } - @Autowired RestTemplate restTemplate; @RequestMapping("/server-location") public String serverLocation() { - String servLoc = this.restTemplate.getForObject("http://ping-server/locaus", String.class); - return servLoc; + return this.restTemplate.getForObject("http://ping-server/locaus", String.class); } public static void main(String[] args) { diff --git a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppIntegrationTest.java b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppIntegrationTest.java index 4134880fa6..2ad9ca4797 100644 --- a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppIntegrationTest.java +++ b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppIntegrationTest.java @@ -1,6 +1,5 @@ package com.baeldung.spring.cloud.ribbon.client; -import static org.assertj.core.api.BDDAssertions.then; import static org.junit.Assert.assertEquals; import org.junit.After; @@ -13,7 +12,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; @@ -43,7 +41,7 @@ public class ServerLocationAppIntegrationTest { private TestRestTemplate testRestTemplate; @Test - public void loadBalancingServersTest() throws InterruptedException { + public void loadBalancingServersTest() { ResponseEntity response = this.testRestTemplate.getForEntity("http://localhost:" + this.port + "/server-location", String.class); assertEquals(response.getBody(), "Australia"); } diff --git a/spring-cloud/spring-cloud-ribbon-retry/pom.xml b/spring-cloud/spring-cloud-ribbon-retry/pom.xml index e0075b4f41..f167aaa56e 100644 --- a/spring-cloud/spring-cloud-ribbon-retry/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-retry/pom.xml @@ -10,10 +10,9 @@ pom - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -45,7 +44,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} 0 diff --git a/spring-cloud/spring-cloud-security/pom.xml b/spring-cloud/spring-cloud-security/pom.xml index d9072af91b..001c9a5c7e 100644 --- a/spring-cloud/spring-cloud-security/pom.xml +++ b/spring-cloud/spring-cloud-security/pom.xml @@ -9,10 +9,9 @@ pom - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -34,7 +33,7 @@ - 2020.0.3 + 2021.0.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml index ba6cee1fce..1c8fa4e694 100644 --- a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml +++ b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml @@ -18,8 +18,8 @@ - + junit junit diff --git a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml index 00e9e7c328..d952d5095e 100644 --- a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml +++ b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml @@ -9,9 +9,8 @@ com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../../parent-boot-2 + spring-cloud-stream + 1.0.0-SNAPSHOT diff --git a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kinesis/pom.xml b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kinesis/pom.xml index f542d78620..c7d3f5d12c 100644 --- a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kinesis/pom.xml +++ b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kinesis/pom.xml @@ -8,9 +8,8 @@ com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../../parent-boot-2 + spring-cloud-stream + 1.0.0-SNAPSHOT diff --git a/spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit/pom.xml b/spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit/pom.xml index 6ca9e89031..8397f5eb25 100644 --- a/spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit/pom.xml +++ b/spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit/pom.xml @@ -12,7 +12,6 @@ com.baeldung spring-cloud-stream 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-task/pom.xml b/spring-cloud/spring-cloud-task/pom.xml index 0cfc62bdbb..e1567b300f 100644 --- a/spring-cloud/spring-cloud-task/pom.xml +++ b/spring-cloud/spring-cloud-task/pom.xml @@ -10,10 +10,9 @@ pom - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -48,8 +47,8 @@ - 2020.0.3 - 2.3.3 + 2021.0.0 + 2.4.0 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/com/baeldung/SpringContextTest.java index 32224bf91b..e1a4255579 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/com/baeldung/SpringContextTest.java @@ -3,7 +3,7 @@ package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -12,7 +12,7 @@ import com.baeldung.task.TaskDemo; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootApplication -@ContextConfiguration(classes = { JobConfiguration.class, TaskDemo.class }, initializers = { ConfigFileApplicationContextInitializer.class }) +@ContextConfiguration(classes = { JobConfiguration.class, TaskDemo.class }, initializers = { ConfigDataApplicationContextInitializer.class }) public class SpringContextTest { @Test diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index 131d58c967..f24861ed6e 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -10,10 +10,9 @@ Demo project for Spring Boot - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -78,7 +77,7 @@ - Greenwich.RELEASE + 2020.0.3 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/application.yml b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml index 1c75ac21e6..cb0b2d60fd 100644 --- a/spring-cloud/spring-cloud-vault/src/main/resources/application.yml +++ b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml @@ -1,11 +1,34 @@ -spring: - application: - name: fakebank - - datasource: - url: jdbc:mysql://localhost:3306/fakebank?serverTimezone=GMT-3 - hikari: connection-test-query: select 1 - idle-timeout: 5000 - max-lifetime: 120000 - maximum-pool-size: 5 - minimum-idle: 5 +spring: + application: + name: fakebank + datasource: + url: jdbc:mysql://localhost:3306/fakebank?serverTimezone=GMT-3 + hikari: + connection-test-query: select 1 + idle-timeout: 5000 + max-lifetime: 120000 + maximum-pool-size: 5 + minimum-idle: 5 + cloud: + vault: + uri: https://localhost:8200 + connection-timeout: 5000 + read-timeout: 15000 + ssl: + trust-store: classpath:/vault.jks + trust-store-password: changeit + generic: + enabled: true + application-name: fakebank + # kv: + # enabled: false + # backend: kv + # application-name: fakebank + database: + enabled: true + role: fakebank-accounts-ro + backend: database + username-property: spring.datasource.username + password-property: spring.datasource.password + config: + import: vault:// \ No newline at end of file diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml deleted file mode 100644 index 7d38b06c0f..0000000000 --- a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,37 +0,0 @@ -spring: - cloud: - vault: - uri: https://localhost:8200 - connection-timeout: 5000 - read-timeout: 15000 - - ssl: - trust-store: classpath:/vault.jks - trust-store-password: changeit - - generic: - enabled: true - application-name: fakebank - -# kv: -# enabled: false -# backend: kv -# application-name: fakebank -# - database: - enabled: true - role: fakebank-accounts-rw - backend: database - username-property: spring.datasource.username - password-property: spring.datasource.password -# -# - - - - - - - - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml index 8e7b87c220..8248884632 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml @@ -68,16 +68,6 @@ spring-boot-starter-test ${spring-boot.version} - - org.hamcrest - hamcrest-core - ${hamcrest-core.version} - test - - - 1.3 - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/pom.xml b/spring-cloud/spring-cloud-zookeeper/pom.xml index 79eabf74f0..3fb899ec47 100644 --- a/spring-cloud/spring-cloud-zookeeper/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/pom.xml @@ -18,8 +18,4 @@ HelloWorld - - 5.2.7.RELEASE - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul-eureka-integration/pom.xml b/spring-cloud/spring-cloud-zuul-eureka-integration/pom.xml index 89d0d2c942..ceb85fe080 100644 --- a/spring-cloud/spring-cloud-zuul-eureka-integration/pom.xml +++ b/spring-cloud/spring-cloud-zuul-eureka-integration/pom.xml @@ -13,7 +13,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml b/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml index 0ba93282b9..13bfabeb3b 100644 --- a/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml +++ b/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud-zuul-fallback 1.0.0-SNAPSHOT - ../pom.xml diff --git a/spring-cloud/spring-cloud-zuul-fallback/pom.xml b/spring-cloud/spring-cloud-zuul-fallback/pom.xml index 1aa29e867d..d55930c6e8 100644 --- a/spring-cloud/spring-cloud-zuul-fallback/pom.xml +++ b/spring-cloud/spring-cloud-zuul-fallback/pom.xml @@ -12,7 +12,6 @@ com.baeldung.spring.cloud spring-cloud 1.0.0-SNAPSHOT - .. diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml index 0590774bef..7e56a8c359 100644 --- a/spring-cloud/spring-cloud-zuul/pom.xml +++ b/spring-cloud/spring-cloud-zuul/pom.xml @@ -10,10 +10,9 @@ pom - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT @@ -35,7 +34,7 @@ org.springframework.cloud spring-cloud-dependencies - ${spring-cloud.version} + ${spring-cloud-dependencies.version} pom import @@ -81,7 +80,7 @@ - 2020.0.3 + 2021.0.0 2.2.7.RELEASE diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml index d2b28643fa..2969b5eed9 100644 --- a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml @@ -43,6 +43,7 @@ 2.2.0.RELEASE 2.4.7 + 2020.0.4 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/README.md b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/README.md new file mode 100644 index 0000000000..91a0c5503b --- /dev/null +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Customizing Zuul Exceptions](https://www.baeldung.com/zuul-customize-exception) diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/pom.xml b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/pom.xml index 7c3f668473..3e32a91a41 100644 --- a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/pom.xml +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/pom.xml @@ -27,16 +27,6 @@ spring-test test - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorApplication.java b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorApplication.java new file mode 100644 index 0000000000..ae8c3040ef --- /dev/null +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.zuul.filter; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +@EnableZuulProxy +@SpringBootApplication +public class CustomZuulErrorApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(CustomZuulErrorApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilter.java b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilter.java new file mode 100644 index 0000000000..d3e52843eb --- /dev/null +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilter.java @@ -0,0 +1,62 @@ +package com.baeldung.spring.cloud.zuul.filter; + +import java.net.ConnectException; +import java.time.Instant; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.exception.ZuulException; + +@Component +public class CustomZuulErrorFilter extends ZuulFilter { + + private static final Logger log = LoggerFactory.getLogger(CustomZuulErrorFilter.class); + + private static final String RESPONSE_BODY = "{\n" + " \"timestamp\": " + "\"" + Instant.now() + .toString() + "\"" + ",\n" + " \"status\": 503,\n" + " \"error\": \"Service Unavailable\"\n" + "}"; + + @Override + public Object run() { + RequestContext context = RequestContext.getCurrentContext(); + Throwable throwable = context.getThrowable(); + + if (throwable instanceof ZuulException) { + final ZuulException zuulException = (ZuulException) throwable; + log.error("Zuul exception: " + zuulException.getMessage()); + + if (throwable.getCause().getCause().getCause() instanceof ConnectException) { + + // reset throwable to prevent further error handling in follow up filters + context.remove("throwable"); + + // set custom response attributes + context.setResponseBody(RESPONSE_BODY); + context.getResponse() + .setContentType("application/json"); + context.setResponseStatusCode(503); + } + + } + return null; + } + + @Override + public boolean shouldFilter() { + return true; + } + + @Override + public int filterOrder() { + return -1; + } + + @Override + public String filterType() { + return "error"; + } + +} diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/ZuulConfiguration.java b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/ZuulConfiguration.java new file mode 100644 index 0000000000..3122862050 --- /dev/null +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/java/com/baeldung/spring/cloud/zuul/filter/ZuulConfiguration.java @@ -0,0 +1,98 @@ +package com.baeldung.spring.cloud.zuul.filter; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.cglib.proxy.Callback; +import org.springframework.cglib.proxy.CallbackFilter; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; +import org.springframework.cglib.proxy.NoOp; +import org.springframework.cloud.netflix.zuul.filters.RouteLocator; +import org.springframework.cloud.netflix.zuul.web.ZuulController; +import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Fix for Zuul configuration with Spring Boot 2.5.x + Zuul - "NoSuchMethodError: ErrorController.getErrorPath()": + */ +@Configuration +public class ZuulConfiguration { + /** + * The path returned by ErrorController.getErrorPath() with Spring Boot < 2.5 + * (and no longer available on Spring Boot >= 2.5). + */ + private static final String ERROR_PATH = "/error"; + private static final String METHOD = "lookupHandler"; + + /** + * Constructs a new bean post-processor for Zuul. + * + * @param routeLocator the route locator. + * @param zuulController the Zuul controller. + * @param errorController the error controller. + * @return the new bean post-processor. + */ + @Bean + public ZuulPostProcessor zuulPostProcessor(@Autowired RouteLocator routeLocator, @Autowired ZuulController zuulController, @Autowired(required = false) ErrorController errorController) { + return new ZuulPostProcessor(routeLocator, zuulController, errorController); + } + + private enum LookupHandlerCallbackFilter implements CallbackFilter { + INSTANCE; + + @Override + public int accept(Method method) { + if (METHOD.equals(method.getName())) { + return 0; + } + return 1; + } + } + + private enum LookupHandlerMethodInterceptor implements MethodInterceptor { + INSTANCE; + + @Override + public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + if (ERROR_PATH.equals(args[0])) { + // by entering this branch we avoid the ZuulHandlerMapping.lookupHandler method to trigger the + // NoSuchMethodError + return null; + } + return methodProxy.invokeSuper(target, args); + } + } + + private static final class ZuulPostProcessor implements BeanPostProcessor { + + private final RouteLocator routeLocator; + private final ZuulController zuulController; + private final boolean hasErrorController; + + ZuulPostProcessor(RouteLocator routeLocator, ZuulController zuulController, ErrorController errorController) { + this.routeLocator = routeLocator; + this.zuulController = zuulController; + this.hasErrorController = (errorController != null); + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (hasErrorController && (bean instanceof ZuulHandlerMapping)) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(ZuulHandlerMapping.class); + enhancer.setCallbackFilter(LookupHandlerCallbackFilter.INSTANCE); // only for lookupHandler + enhancer.setCallbacks(new Callback[] { LookupHandlerMethodInterceptor.INSTANCE, NoOp.INSTANCE }); + Constructor ctor = ZuulHandlerMapping.class.getConstructors()[0]; + return enhancer.create(ctor.getParameterTypes(), new Object[] { routeLocator, zuulController }); + } + return bean; + } + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/resources/application.yml b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/resources/application.yml index 855020a40e..bd517b8a6b 100644 --- a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/resources/application.yml +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/main/resources/application.yml @@ -1,5 +1,8 @@ zuul: + SendErrorFilter: + post: + disable: true routes: foos: path: /foos/** - url: http://localhost:8081/spring-zuul-foos-resource/foos + url: http://localhost:8081/spring-zuul-foos-resource/foos \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/test/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilterLiveTest.java b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/test/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilterLiveTest.java new file mode 100644 index 0000000000..da2588966d --- /dev/null +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-ui/src/test/java/com/baeldung/spring/cloud/zuul/filter/CustomZuulErrorFilterLiveTest.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.cloud.zuul.filter; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + +public class CustomZuulErrorFilterLiveTest { + + @Test + public void whenSendRequestWithoutService_thenCustomError() { + final Response response = RestAssured.get("http://localhost:8080/foos/1"); + assertEquals(503, response.getStatusCode()); + } + + @Test + public void whenSendRequestWithoutCustomErrorFilter_thenError() { + final Response response = RestAssured.get("http://localhost:8080/foos/1"); + assertEquals(500, response.getStatusCode()); + } + +} diff --git a/spring-core-2/pom.xml b/spring-core-2/pom.xml index de5c7c0d4d..719bf56e0b 100644 --- a/spring-core-2/pom.xml +++ b/spring-core-2/pom.xml @@ -129,21 +129,6 @@ spring-test test - - org.assertj - assertj-core - test - - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - net.javacrumbs.shedlock @@ -203,9 +188,7 @@ 5.2.5.Final - 25.1-jre 3.6 - 3.6.1 2.1.0 3.22.0-GA 3.2.2 diff --git a/spring-core-3/pom.xml b/spring-core-3/pom.xml index 50d2e7ac5e..9e777a4a03 100644 --- a/spring-core-3/pom.xml +++ b/spring-core-3/pom.xml @@ -55,18 +55,6 @@ ${spring.version} test - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - diff --git a/spring-core-4/pom.xml b/spring-core-4/pom.xml index 5706b2ee75..2874931738 100644 --- a/spring-core-4/pom.xml +++ b/spring-core-4/pom.xml @@ -55,43 +55,24 @@ ${spring.version} test - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - org.awaitility awaitility ${awaitility.version} test - - org.assertj - assertj-core - ${assertj-core.version} - test - javax.servlet javax.servlet-api - 4.0.0 + ${servlet-api.version} 1.3.2 2.2.2.RELEASE - 28.2-jre 4.0.2 - 2.9.1 + 4.0.0 \ No newline at end of file diff --git a/spring-core-5/README.md b/spring-core-5/README.md index cf90d9ffc3..b6c9ba606a 100644 --- a/spring-core-5/README.md +++ b/spring-core-5/README.md @@ -1,6 +1,6 @@ ## Spring Core -This module contains articles about core Spring functionality +This module contains articles about core Spring functionality. ## Relevant Articles: @@ -8,4 +8,6 @@ This module contains articles about core Spring functionality - [Solving Spring’s “not eligible for auto-proxying” Warning](https://www.baeldung.com/spring-not-eligible-for-auto-proxying) - [Spring Bean Names](https://www.baeldung.com/spring-bean-names) - [AliasFor Annotation in Spring](https://www.baeldung.com/spring-aliasfor-annotation) -- More articles: [[<-- prev]](/spring-core-4) +- [A Quick Guide to the Spring @Lazy Annotation](https://www.baeldung.com/spring-lazy-annotation) +- [Finding the Spring Version](https://www.baeldung.com/spring-find-version) +- More articles: [[<-- prev]](../spring-core-4) diff --git a/spring-core/src/main/java/com/baeldung/lazy/AppConfig.java b/spring-core-5/src/main/java/com/baeldung/lazy/AppConfig.java similarity index 100% rename from spring-core/src/main/java/com/baeldung/lazy/AppConfig.java rename to spring-core-5/src/main/java/com/baeldung/lazy/AppConfig.java diff --git a/spring-core/src/main/java/com/baeldung/lazy/City.java b/spring-core-5/src/main/java/com/baeldung/lazy/City.java similarity index 100% rename from spring-core/src/main/java/com/baeldung/lazy/City.java rename to spring-core-5/src/main/java/com/baeldung/lazy/City.java diff --git a/spring-core/src/main/java/com/baeldung/lazy/Country.java b/spring-core-5/src/main/java/com/baeldung/lazy/Country.java similarity index 100% rename from spring-core/src/main/java/com/baeldung/lazy/Country.java rename to spring-core-5/src/main/java/com/baeldung/lazy/Country.java diff --git a/spring-core/src/main/java/com/baeldung/lazy/Region.java b/spring-core-5/src/main/java/com/baeldung/lazy/Region.java similarity index 100% rename from spring-core/src/main/java/com/baeldung/lazy/Region.java rename to spring-core-5/src/main/java/com/baeldung/lazy/Region.java diff --git a/spring-5/src/main/java/com/baeldung/version/VersionObtainer.java b/spring-core-5/src/main/java/com/baeldung/version/VersionObtainer.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/version/VersionObtainer.java rename to spring-core-5/src/main/java/com/baeldung/version/VersionObtainer.java diff --git a/spring-core/src/test/java/com/baeldung/Lazy/LazyAnnotationUnitTest.java b/spring-core-5/src/test/java/com/baeldung/lazy/LazyAnnotationUnitTest.java similarity index 89% rename from spring-core/src/test/java/com/baeldung/Lazy/LazyAnnotationUnitTest.java rename to spring-core-5/src/test/java/com/baeldung/lazy/LazyAnnotationUnitTest.java index 187d573557..d0dfe55b84 100644 --- a/spring-core/src/test/java/com/baeldung/Lazy/LazyAnnotationUnitTest.java +++ b/spring-core-5/src/test/java/com/baeldung/lazy/LazyAnnotationUnitTest.java @@ -1,8 +1,5 @@ -package com.baeldung.Lazy; +package com.baeldung.lazy; -import com.baeldung.lazy.AppConfig; -import com.baeldung.lazy.Country; -import com.baeldung.lazy.Region; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; diff --git a/spring-5/src/test/java/com/baeldung/version/VersionObtainerUnitTest.java b/spring-core-5/src/test/java/com/baeldung/version/VersionObtainerUnitTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/version/VersionObtainerUnitTest.java rename to spring-core-5/src/test/java/com/baeldung/version/VersionObtainerUnitTest.java diff --git a/spring-core-5/src/test/resources/logback-test.xml b/spring-core-5/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-core-5/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-core/README.md b/spring-core/README.md index b8d46f6b34..ffcbf4757b 100644 --- a/spring-core/README.md +++ b/spring-core/README.md @@ -1,15 +1,15 @@ ## Spring Core -This module contains articles about core Spring functionality +This module contains articles about core Spring functionality. ### Relevant Articles: - [Introduction to Spring’s StreamUtils](https://www.baeldung.com/spring-stream-utils) -- [A Quick Guide to the Spring @Lazy Annotation](https://www.baeldung.com/spring-lazy-annotation) - [BeanNameAware and BeanFactoryAware Interfaces in Spring](https://www.baeldung.com/spring-bean-name-factory-aware) - [Access a File from the Classpath in a Spring Application](https://www.baeldung.com/spring-classpath-file-access) - [Spring Application Context Events](https://www.baeldung.com/spring-context-events) - [What is a Spring Bean?](https://www.baeldung.com/spring-bean) - [Spring PostConstruct and PreDestroy Annotations](https://www.baeldung.com/spring-postconstruct-predestroy) -- More articles: [[next -->]](/spring-core-2) +- [Intro to the Spring ClassPathXmlApplicationContext](http://www.baeldung.com/spring-classpathxmlapplicationcontext) +- More articles: [[next -->]](../spring-core-2) diff --git a/spring-core/pom.xml b/spring-core/pom.xml index ab41670224..d8eaf22220 100644 --- a/spring-core/pom.xml +++ b/spring-core/pom.xml @@ -57,12 +57,6 @@ ${mockito.spring.boot.version} test - - org.assertj - assertj-core - ${assertj.version} - test - commons-io commons-io @@ -86,10 +80,8 @@ 1.4.4.RELEASE 1 - 20.0 1.5.2.RELEASE 1.10.19 - 3.12.2 \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/applicationcontext/README.md b/spring-core/src/test/java/com/baeldung/applicationcontext/README.md deleted file mode 100644 index 211007e0cf..0000000000 --- a/spring-core/src/test/java/com/baeldung/applicationcontext/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: -- [Introduction to Java Servlets](http://www.baeldung.com/intro-to-servlets) -- [Intro to the Spring ClassPathXmlApplicationContext](http://www.baeldung.com/spring-classpathxmlapplicationcontext) diff --git a/spring-data-rest-2/README.md b/spring-data-rest-2/README.md new file mode 100644 index 0000000000..04a54291b0 --- /dev/null +++ b/spring-data-rest-2/README.md @@ -0,0 +1,20 @@ +## Spring Data REST + +This module contains articles about Spring Data REST + +### Relevant Articles: +- [Guide to Spring Data REST Validators](https://www.baeldung.com/spring-data-rest-validators) +- [Spring Data Web Support](https://www.baeldung.com/spring-data-web-support) +- [Spring REST and HAL Browser](https://www.baeldung.com/spring-rest-hal) + +### The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +# Running the project +The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways: +* Run the `main` method from `SpringDataRestApplication` +* Use the Maven Spring Boot plugin: `mvn spring-boot:run` +* Package the application as a JAR and run it using `java -jar intro-spring-data-rest-2.jar` + +# Viewing the running application +To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser diff --git a/spring-data-rest-2/pom.xml b/spring-data-rest-2/pom.xml new file mode 100644 index 0000000000..cf3265c46d --- /dev/null +++ b/spring-data-rest-2/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + spring-data-rest-2 + 1.0 + spring-data-rest-2 + jar + Intro to Spring Data REST + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.data + spring-data-rest-hal-explorer + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-starter-test + test + + + com.h2database + h2 + runtime + + + com.querydsl + querydsl-apt + + + com.querydsl + querydsl-jpa + + + + + ${project.artifactId} + + + com.mysema.maven + maven-apt-plugin + ${maven.version} + + + generate-sources + + process + + + target/generated-sources + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + com.baeldung.books.SpringDataRestApplication + 1.0 + + + \ No newline at end of file diff --git a/spring-data-rest-2/src/main/java/com/baeldung/books/SpringDataRestApplication.java b/spring-data-rest-2/src/main/java/com/baeldung/books/SpringDataRestApplication.java new file mode 100644 index 0000000000..097a6aabd7 --- /dev/null +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/SpringDataRestApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.books; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringDataRestApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringDataRestApplication.class, args); + } + +} diff --git a/spring-data-rest-2/src/main/java/com/baeldung/books/config/DbConfig.java b/spring-data-rest-2/src/main/java/com/baeldung/books/config/DbConfig.java new file mode 100644 index 0000000000..3fe7516537 --- /dev/null +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/config/DbConfig.java @@ -0,0 +1,65 @@ +package com.baeldung.books.config; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +@Configuration +@EnableJpaRepositories(basePackages = "com.baeldung.books.repositories") +public class DbConfig { + + @Autowired + private Environment env; + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(env.getProperty("driverClassName")); + dataSource.setUrl(env.getProperty("url")); + dataSource.setUsername(env.getProperty("user")); + dataSource.setPassword(env.getProperty("password")); + return dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.books.models" }); + em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + em.setJpaProperties(additionalProperties()); + return em; + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + if (env.getProperty("hibernate.hbm2ddl.auto") != null) { + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + } + if (env.getProperty("hibernate.dialect") != null) { + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + } + if (env.getProperty("hibernate.show_sql") != null) { + hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); + } + return hibernateProperties; + } + +} + +@Configuration +@Profile("h2") +@PropertySource("classpath:persistence-h2.properties") +class H2Config { +} diff --git a/spring-data-rest-2/src/main/java/com/baeldung/books/config/RestConfig.java b/spring-data-rest-2/src/main/java/com/baeldung/books/config/RestConfig.java new file mode 100644 index 0000000000..8bcde7c97b --- /dev/null +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/config/RestConfig.java @@ -0,0 +1,21 @@ +package com.baeldung.books.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.rest.core.config.RepositoryRestConfiguration; +import org.springframework.data.rest.core.mapping.ExposureConfiguration; +import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; +import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.config.annotation.CorsRegistry; + +import com.baeldung.books.models.WebsiteUser; + +@Configuration +public class RestConfig implements RepositoryRestConfigurer { + + @Override + public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration, + CorsRegistry cors) { + ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration(); + config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH)); + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java b/spring-data-rest-2/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java similarity index 97% rename from spring-data-rest/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java rename to spring-data-rest-2/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java index bbaf9a2771..3301443203 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/config/ValidatorEventRegister.java @@ -1,30 +1,30 @@ -package com.baeldung.books.config; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener; -import org.springframework.validation.Validator; - -@Configuration -public class ValidatorEventRegister implements InitializingBean { - - @Autowired - ValidatingRepositoryEventListener validatingRepositoryEventListener; - - @Autowired - private Map validators; - - @Override - public void afterPropertiesSet() throws Exception { - List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete"); - - for (Map.Entry entry : validators.entrySet()) { - events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); - } - } -} +package com.baeldung.books.config; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener; +import org.springframework.validation.Validator; + +@Configuration +public class ValidatorEventRegister implements InitializingBean { + + @Autowired + ValidatingRepositoryEventListener validatingRepositoryEventListener; + + @Autowired + private Map validators; + + @Override + public void afterPropertiesSet() throws Exception { + List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete"); + + for (Map.Entry entry : validators.entrySet()) { + events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); + } + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java b/spring-data-rest-2/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java similarity index 97% rename from spring-data-rest/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java rename to spring-data-rest-2/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java index 4a961e5250..e87176af69 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/exception/handlers/RestResponseEntityExceptionHandler.java @@ -1,26 +1,26 @@ -package com.baeldung.books.exception.handlers; - -import org.springframework.data.rest.core.RepositoryConstraintViolationException; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.ObjectError; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -import java.util.stream.Collectors; - -@ControllerAdvice -public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { - - @ExceptionHandler({ RepositoryConstraintViolationException.class }) - public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { - RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; - - String errors = nevEx.getErrors().getAllErrors().stream().map(ObjectError::toString).collect(Collectors.joining("\n")); - return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); - } - +package com.baeldung.books.exception.handlers; + +import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import java.util.stream.Collectors; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler({ RepositoryConstraintViolationException.class }) + public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { + RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; + + String errors = nevEx.getErrors().getAllErrors().stream().map(ObjectError::toString).collect(Collectors.joining("\n")); + return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); + } + } \ No newline at end of file diff --git a/spring-data-rest/src/main/java/com/baeldung/books/models/WebsiteUser.java b/spring-data-rest-2/src/main/java/com/baeldung/books/models/WebsiteUser.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/books/models/WebsiteUser.java rename to spring-data-rest-2/src/main/java/com/baeldung/books/models/WebsiteUser.java diff --git a/spring-data-rest/src/main/java/com/baeldung/books/repositories/UserRepository.java b/spring-data-rest-2/src/main/java/com/baeldung/books/repositories/UserRepository.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/books/repositories/UserRepository.java rename to spring-data-rest-2/src/main/java/com/baeldung/books/repositories/UserRepository.java diff --git a/spring-data-rest/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java b/spring-data-rest-2/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java similarity index 96% rename from spring-data-rest/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java rename to spring-data-rest-2/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java index ad7511c2ba..c7b05244df 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java +++ b/spring-data-rest-2/src/main/java/com/baeldung/books/validators/WebsiteUserValidator.java @@ -1,33 +1,33 @@ -package com.baeldung.books.validators; - -import org.springframework.stereotype.Component; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -import com.baeldung.books.models.WebsiteUser; - -@Component("beforeCreateWebsiteUserValidator") -public class WebsiteUserValidator implements Validator { - - @Override - public boolean supports(Class clazz) { - return WebsiteUser.class.equals(clazz); - } - - @Override - public void validate(Object obj, Errors errors) { - - WebsiteUser user = (WebsiteUser) obj; - if (checkInputString(user.getName())) { - errors.rejectValue("name", "name.empty"); - } - - if (checkInputString(user.getEmail())) { - errors.rejectValue("email", "email.empty"); - } - } - - private boolean checkInputString(String input) { - return (input == null || input.trim().length() == 0); - } -} +package com.baeldung.books.validators; + +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import com.baeldung.books.models.WebsiteUser; + +@Component("beforeCreateWebsiteUserValidator") +public class WebsiteUserValidator implements Validator { + + @Override + public boolean supports(Class clazz) { + return WebsiteUser.class.equals(clazz); + } + + @Override + public void validate(Object obj, Errors errors) { + + WebsiteUser user = (WebsiteUser) obj; + if (checkInputString(user.getName())) { + errors.rejectValue("name", "name.empty"); + } + + if (checkInputString(user.getEmail())) { + errors.rejectValue("email", "email.empty"); + } + } + + private boolean checkInputString(String input) { + return (input == null || input.trim().length() == 0); + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/halbrowser/App.java b/spring-data-rest-2/src/main/java/com/baeldung/halbrowser/App.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/halbrowser/App.java rename to spring-data-rest-2/src/main/java/com/baeldung/halbrowser/App.java diff --git a/spring-data-rest/src/main/java/com/baeldung/halbrowser/config/DBLoader.java b/spring-data-rest-2/src/main/java/com/baeldung/halbrowser/config/DBLoader.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/halbrowser/config/DBLoader.java rename to spring-data-rest-2/src/main/java/com/baeldung/halbrowser/config/DBLoader.java diff --git a/spring-data-rest/src/main/java/com/baeldung/halbrowser/config/RestConfig.java b/spring-data-rest-2/src/main/java/com/baeldung/halbrowser/config/RestConfig.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/halbrowser/config/RestConfig.java rename to spring-data-rest-2/src/main/java/com/baeldung/halbrowser/config/RestConfig.java diff --git a/spring-data-rest/src/main/java/com/baeldung/halbrowser/data/BookRepository.java b/spring-data-rest-2/src/main/java/com/baeldung/halbrowser/data/BookRepository.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/halbrowser/data/BookRepository.java rename to spring-data-rest-2/src/main/java/com/baeldung/halbrowser/data/BookRepository.java diff --git a/spring-data-rest/src/main/java/com/baeldung/halbrowser/model/Book.java b/spring-data-rest-2/src/main/java/com/baeldung/halbrowser/model/Book.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/halbrowser/model/Book.java rename to spring-data-rest-2/src/main/java/com/baeldung/halbrowser/model/Book.java diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/Application.java b/spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/Application.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/Application.java rename to spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/Application.java diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java b/spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java rename to spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java b/spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java similarity index 100% rename from spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java rename to spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java b/spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java similarity index 82% rename from spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java rename to spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java index a20197dc8b..fa727eff6c 100644 --- a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java +++ b/spring-data-rest-2/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java @@ -1,12 +1,11 @@ package com.baeldung.springdatawebsupport.application.repositories; -import com.baeldung.springdatawebsupport.application.entities.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; +import com.baeldung.springdatawebsupport.application.entities.User; + @Repository public interface UserRepository extends PagingAndSortingRepository, QuerydslPredicateExecutor { diff --git a/spring-data-rest-2/src/main/resources/application.properties b/spring-data-rest-2/src/main/resources/application.properties new file mode 100644 index 0000000000..06cb22a4fe --- /dev/null +++ b/spring-data-rest-2/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.default=h2 \ No newline at end of file diff --git a/spring-data-rest-2/src/main/resources/logback.xml b/spring-data-rest-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-data-rest-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/spring-data-rest-2/src/main/resources/persistence-h2.properties b/spring-data-rest-2/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..d535f9dbe4 --- /dev/null +++ b/spring-data-rest-2/src/main/resources/persistence-h2.properties @@ -0,0 +1,8 @@ +driverClassName=org.h2.Driver +url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 +username=sa +password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/spring-data-rest-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-data-rest-2/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..8fa0a4c239 --- /dev/null +++ b/spring-data-rest-2/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,17 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.books.SpringDataRestApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringDataRestApplication.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-data-rest/src/test/java/com/baeldung/books/validator/SpringDataRestValidatorIntegrationTest.java b/spring-data-rest-2/src/test/java/com/baeldung/books/validator/SpringDataRestValidatorIntegrationTest.java similarity index 100% rename from spring-data-rest/src/test/java/com/baeldung/books/validator/SpringDataRestValidatorIntegrationTest.java rename to spring-data-rest-2/src/test/java/com/baeldung/books/validator/SpringDataRestValidatorIntegrationTest.java diff --git a/spring-data-rest/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java b/spring-data-rest-2/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java similarity index 100% rename from spring-data-rest/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java rename to spring-data-rest-2/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md index ab1991b08f..cbdd8986eb 100644 --- a/spring-data-rest/README.md +++ b/spring-data-rest/README.md @@ -4,15 +4,12 @@ This module contains articles about Spring Data REST ### Relevant Articles: - [Introduction to Spring Data REST](https://www.baeldung.com/spring-data-rest-intro) -- [Guide to Spring Data REST Validators](https://www.baeldung.com/spring-data-rest-validators) - [Working with Relationships in Spring Data REST](https://www.baeldung.com/spring-data-rest-relationships) - [AngularJS CRUD Application with Spring Data REST](https://www.baeldung.com/angularjs-crud-with-spring-data-rest) - [Projections and Excerpts in Spring Data REST](https://www.baeldung.com/spring-data-rest-projections-excerpts) - [Spring Data REST Events with @RepositoryEventHandler](https://www.baeldung.com/spring-data-rest-events) - [Customizing HTTP Endpoints in Spring Data REST](https://www.baeldung.com/spring-data-rest-customize-http-endpoints) - [Spring Boot with SQLite](https://www.baeldung.com/spring-boot-sqlite) -- [Spring Data Web Support](https://www.baeldung.com/spring-data-web-support) -- [Spring REST and HAL Browser](https://www.baeldung.com/spring-rest-hal) ### The Course The "REST With Spring" Classes: http://bit.ly/restwithspring diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index 4a22ce92d1..e223c0488e 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -33,15 +33,6 @@ org.springframework.boot spring-boot-starter-data-jpa - - - org.springframework.data - spring-data-rest-hal-explorer - - - org.springframework.boot - spring-boot-starter-validation - org.springframework.boot spring-boot-autoconfigure diff --git a/spring-data-rest/src/main/java/com/baeldung/books/config/MvcConfig.java b/spring-data-rest/src/main/java/com/baeldung/books/config/MvcConfig.java index 69e984ad06..0065173905 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/config/MvcConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/books/config/MvcConfig.java @@ -1,5 +1,7 @@ package com.baeldung.books.config; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; @@ -22,6 +24,11 @@ public class MvcConfig implements WebMvcConfigurer { configurer.enable(); } + @Bean + WebServerFactoryCustomizer enableDefaultServlet() { + return (factory) -> factory.setRegisterDefaultServlet(true); + } + @Bean AuthorEventHandler authorEventHandler() { return new AuthorEventHandler(); diff --git a/spring-data-rest/src/main/java/com/baeldung/books/config/RestConfig.java b/spring-data-rest/src/main/java/com/baeldung/books/config/RestConfig.java index 8d9ab5952c..1c03fafd5f 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/config/RestConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/books/config/RestConfig.java @@ -1,14 +1,12 @@ package com.baeldung.books.config; -import com.baeldung.books.models.WebsiteUser; -import com.baeldung.books.projections.CustomBook; import org.springframework.context.annotation.Configuration; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; -import org.springframework.data.rest.core.mapping.ExposureConfiguration; import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; -import org.springframework.http.HttpMethod; import org.springframework.web.servlet.config.annotation.CorsRegistry; +import com.baeldung.books.projections.CustomBook; + @Configuration public class RestConfig implements RepositoryRestConfigurer { @@ -16,7 +14,5 @@ public class RestConfig implements RepositoryRestConfigurer { public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration, CorsRegistry cors) { repositoryRestConfiguration.getProjectionConfiguration().addProjection(CustomBook.class); - ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration(); - config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH)); } } diff --git a/spring-data-rest/src/main/java/com/baeldung/books/events/AuthorEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/books/events/AuthorEventHandler.java index b390a529ba..4540fa3b24 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/events/AuthorEventHandler.java +++ b/spring-data-rest/src/main/java/com/baeldung/books/events/AuthorEventHandler.java @@ -1,11 +1,14 @@ package com.baeldung.books.events; -import org.springframework.data.rest.core.annotation.*; +import java.util.logging.Logger; + +import org.springframework.data.rest.core.annotation.HandleAfterCreate; +import org.springframework.data.rest.core.annotation.HandleAfterDelete; +import org.springframework.data.rest.core.annotation.HandleBeforeCreate; +import org.springframework.data.rest.core.annotation.HandleBeforeDelete; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; import com.baeldung.books.models.Author; -import com.baeldung.books.models.Book; - -import java.util.logging.Logger; @RepositoryEventHandler public class AuthorEventHandler { diff --git a/spring-data-rest/src/main/java/com/baeldung/books/events/BookEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/books/events/BookEventHandler.java index 0afb3a6279..fc0d9b4098 100644 --- a/spring-data-rest/src/main/java/com/baeldung/books/events/BookEventHandler.java +++ b/spring-data-rest/src/main/java/com/baeldung/books/events/BookEventHandler.java @@ -2,8 +2,6 @@ package com.baeldung.books.events; import java.util.logging.Logger; -import org.apache.commons.logging.Log; -import org.springframework.data.rest.core.annotation.HandleAfterDelete; import org.springframework.data.rest.core.annotation.HandleBeforeCreate; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; diff --git a/spring-di-2/README.md b/spring-di-2/README.md index f41976c3f0..5989e6269b 100644 --- a/spring-di-2/README.md +++ b/spring-di-2/README.md @@ -9,4 +9,6 @@ This module contains articles about dependency injection with Spring - [Spring – Injecting Collections](https://www.baeldung.com/spring-injecting-collections) - [Wiring in Spring: @Autowired, @Resource and @Inject](https://www.baeldung.com/spring-annotations-resource-inject-autowire) - [Injecting Spring Beans into Unmanaged Objects](https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects) -- More articles: [[<-- prev]](/spring-di) +- [Constructor Dependency Injection in Spring](https://www.baeldung.com/constructor-injection-in-spring) +- [Circular Dependencies in Spring](https://www.baeldung.com/circular-dependencies-in-spring) +- More articles: [[<-- prev]](../spring-di)[[more -->]](../spring-di-3) diff --git a/spring-di-2/pom.xml b/spring-di-2/pom.xml index 7d3f4c7b33..d3be846424 100644 --- a/spring-di-2/pom.xml +++ b/spring-di-2/pom.xml @@ -14,37 +14,40 @@ ../parent-spring-5 + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + - org.springframework - spring-test - ${spring.version} + org.springframework.boot + spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa - ${spring-boot.version} - - - org.springframework.boot - spring-boot-starter-web - ${spring-boot.version} org.springframework spring-aspects - ${spring.version} - - - org.projectlombok - lombok - ${lombok.version} javax.inject javax.inject ${javax.inject.version} + + org.springframework.boot + spring-boot-starter-test + @@ -74,7 +77,7 @@ - 2.3.1.RELEASE + 2.6.1 1.11 1 diff --git a/spring-di/src/main/java/com/baeldung/circulardependency/CircularDependencyA.java b/spring-di-2/src/main/java/com/baeldung/circulardependency/CircularDependencyA.java similarity index 100% rename from spring-di/src/main/java/com/baeldung/circulardependency/CircularDependencyA.java rename to spring-di-2/src/main/java/com/baeldung/circulardependency/CircularDependencyA.java diff --git a/spring-di/src/main/java/com/baeldung/circulardependency/CircularDependencyB.java b/spring-di-2/src/main/java/com/baeldung/circulardependency/CircularDependencyB.java similarity index 100% rename from spring-di/src/main/java/com/baeldung/circulardependency/CircularDependencyB.java rename to spring-di-2/src/main/java/com/baeldung/circulardependency/CircularDependencyB.java diff --git a/spring-di/src/main/java/com/baeldung/constructordi/Config.java b/spring-di-2/src/main/java/com/baeldung/constructordi/Config.java similarity index 99% rename from spring-di/src/main/java/com/baeldung/constructordi/Config.java rename to spring-di-2/src/main/java/com/baeldung/constructordi/Config.java index 07568018f3..d3c6b2d231 100644 --- a/spring-di/src/main/java/com/baeldung/constructordi/Config.java +++ b/spring-di-2/src/main/java/com/baeldung/constructordi/Config.java @@ -1,11 +1,10 @@ package com.baeldung.constructordi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - import com.baeldung.constructordi.domain.Engine; import com.baeldung.constructordi.domain.Transmission; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.baeldung.constructordi") diff --git a/spring-di/src/main/java/com/baeldung/constructordi/SpringRunner.java b/spring-di-2/src/main/java/com/baeldung/constructordi/SpringRunner.java similarity index 99% rename from spring-di/src/main/java/com/baeldung/constructordi/SpringRunner.java rename to spring-di-2/src/main/java/com/baeldung/constructordi/SpringRunner.java index abbe97a4bd..75a1af47ee 100644 --- a/spring-di/src/main/java/com/baeldung/constructordi/SpringRunner.java +++ b/spring-di-2/src/main/java/com/baeldung/constructordi/SpringRunner.java @@ -1,11 +1,10 @@ package com.baeldung.constructordi; +import com.baeldung.constructordi.domain.Car; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; -import com.baeldung.constructordi.domain.Car; - public class SpringRunner { public static void main(String[] args) { Car toyota = getCarFromXml(); diff --git a/spring-di/src/main/java/com/baeldung/constructordi/domain/Car.java b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Car.java similarity index 85% rename from spring-di/src/main/java/com/baeldung/constructordi/domain/Car.java rename to spring-di-2/src/main/java/com/baeldung/constructordi/domain/Car.java index 9f68ba5cd9..bbe9b669d8 100644 --- a/spring-di/src/main/java/com/baeldung/constructordi/domain/Car.java +++ b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Car.java @@ -5,8 +5,9 @@ import org.springframework.stereotype.Component; @Component public class Car { - private Engine engine; - private Transmission transmission; + + private final Engine engine; + private final Transmission transmission; @Autowired public Car(Engine engine, Transmission transmission) { diff --git a/spring-di/src/main/java/com/baeldung/constructordi/domain/Engine.java b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Engine.java similarity index 81% rename from spring-di/src/main/java/com/baeldung/constructordi/domain/Engine.java rename to spring-di-2/src/main/java/com/baeldung/constructordi/domain/Engine.java index f2987988eb..ed9c1f4d1c 100644 --- a/spring-di/src/main/java/com/baeldung/constructordi/domain/Engine.java +++ b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Engine.java @@ -1,8 +1,9 @@ package com.baeldung.constructordi.domain; public class Engine { - private String type; - private int volume; + + private final String type; + private final int volume; public Engine(String type, int volume) { this.type = type; diff --git a/spring-di/src/main/java/com/baeldung/constructordi/domain/Transmission.java b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Transmission.java similarity index 88% rename from spring-di/src/main/java/com/baeldung/constructordi/domain/Transmission.java rename to spring-di-2/src/main/java/com/baeldung/constructordi/domain/Transmission.java index 85271e1f2a..00060e4921 100644 --- a/spring-di/src/main/java/com/baeldung/constructordi/domain/Transmission.java +++ b/spring-di-2/src/main/java/com/baeldung/constructordi/domain/Transmission.java @@ -1,7 +1,8 @@ package com.baeldung.constructordi.domain; public class Transmission { - private String type; + + private final String type; public Transmission(String type) { this.type = type; diff --git a/spring-di/src/main/resources/constructordi.xml b/spring-di-2/src/main/resources/constructordi.xml similarity index 100% rename from spring-di/src/main/resources/constructordi.xml rename to spring-di-2/src/main/resources/constructordi.xml diff --git a/spring-di/src/test/java/com/baeldung/circulardependency/CircularDependencyIntegrationTest.java b/spring-di-2/src/test/java/com/baeldung/circulardependency/CircularDependencyIntegrationTest.java similarity index 100% rename from spring-di/src/test/java/com/baeldung/circulardependency/CircularDependencyIntegrationTest.java rename to spring-di-2/src/test/java/com/baeldung/circulardependency/CircularDependencyIntegrationTest.java diff --git a/spring-di/src/test/java/com/baeldung/circulardependency/TestConfig.java b/spring-di-2/src/test/java/com/baeldung/circulardependency/TestConfig.java similarity index 100% rename from spring-di/src/test/java/com/baeldung/circulardependency/TestConfig.java rename to spring-di-2/src/test/java/com/baeldung/circulardependency/TestConfig.java diff --git a/spring-di/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java b/spring-di-2/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java similarity index 99% rename from spring-di/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java rename to spring-di-2/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java index 7bd0ad0c86..4c4e622629 100644 --- a/spring-di/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java +++ b/spring-di-2/src/test/java/com/baeldung/constructordi/ConstructorDependencyInjectionIntegrationTest.java @@ -1,7 +1,6 @@ package com.baeldung.constructordi; -import static org.assertj.core.api.Assertions.assertThat; - +import com.baeldung.constructordi.domain.Car; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; @@ -11,7 +10,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import com.baeldung.constructordi.domain.Car; +import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = Config.class) diff --git a/spring-di-2/src/test/java/com/baeldung/di/aspectj/PersonUnitTest.java b/spring-di-2/src/test/java/com/baeldung/di/aspectj/PersonUnitTest.java index 72ccfbadf3..d0318e96b9 100644 --- a/spring-di-2/src/test/java/com/baeldung/di/aspectj/PersonUnitTest.java +++ b/spring-di-2/src/test/java/com/baeldung/di/aspectj/PersonUnitTest.java @@ -10,10 +10,12 @@ import static org.junit.Assert.assertEquals; @RunWith(SpringRunner.class) @ContextConfiguration(classes = AspectJConfig.class) public class PersonUnitTest { + @Test public void givenUnmanagedObjects_whenInjectingIdService_thenIdValueIsCorrectlySet() { PersonObject personObject = new PersonObject("Baeldung"); personObject.generateId(); + assertEquals(1, personObject.getId()); assertEquals("Baeldung", personObject.getName()); diff --git a/spring-di-2/src/test/resources/logback-test.xml b/spring-di-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-di-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-di-3/README.md b/spring-di-3/README.md new file mode 100644 index 0000000000..9ab7789f37 --- /dev/null +++ b/spring-di-3/README.md @@ -0,0 +1,8 @@ +## Spring Dependency Injection + +This module contains articles about dependency injection with Spring + +### Relevant Articles + +- [@Lookup Annotation in Spring](https://www.baeldung.com/spring-lookup) +- More articles: [[<-- prev]](../spring-di-2) diff --git a/spring-di-3/pom.xml b/spring-di-3/pom.xml new file mode 100644 index 0000000000..0d4bbd01af --- /dev/null +++ b/spring-di-3/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + spring-di-3 + 1.0-SNAPSHOT + spring-di-3 + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + + + + + 2.6.1 + + + \ No newline at end of file diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/App.java b/spring-di-3/src/main/java/com/baeldung/autowiring/App.java new file mode 100644 index 0000000000..d2d0db7a60 --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/App.java @@ -0,0 +1,14 @@ +package com.baeldung.autowiring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + +} diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/controller/CorrectController.java b/spring-di-3/src/main/java/com/baeldung/autowiring/controller/CorrectController.java new file mode 100644 index 0000000000..e0c0d7eeac --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/controller/CorrectController.java @@ -0,0 +1,18 @@ +package com.baeldung.autowiring.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +import com.baeldung.autowiring.service.MyService; + +@Controller +public class CorrectController { + + @Autowired + MyService myService; + + public String control() { + return myService.serve(); + } + +} diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/controller/FlawedController.java b/spring-di-3/src/main/java/com/baeldung/autowiring/controller/FlawedController.java new file mode 100644 index 0000000000..673e686f79 --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/controller/FlawedController.java @@ -0,0 +1,15 @@ +package com.baeldung.autowiring.controller; + +import org.springframework.stereotype.Controller; + +import com.baeldung.autowiring.service.MyService; + +@Controller +public class FlawedController { + + public String control() { + MyService userService = new MyService(); + return userService.serve(); + } + +} diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyComponent.java b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyComponent.java new file mode 100644 index 0000000000..c04ca3f4ba --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyComponent.java @@ -0,0 +1,10 @@ +package com.baeldung.autowiring.service; + +import org.springframework.stereotype.Component; + +@Component +public class MyComponent { + + public void doWork() {} + +} diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyService.java b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyService.java new file mode 100644 index 0000000000..3443dc05de --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyService.java @@ -0,0 +1,19 @@ +package com.baeldung.autowiring.service; + +import org.springframework.beans.factory.annotation.Autowired; + +/** + * The bean corresponding to this class is defined in MyServiceConfiguration + * Alternatively, you could choose to decorate this class with @Component or @Service + */ +public class MyService { + + @Autowired + MyComponent myComponent; + + public String serve() { + myComponent.doWork(); + return "success"; + } + +} diff --git a/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java new file mode 100644 index 0000000000..e30e4f770e --- /dev/null +++ b/spring-di-3/src/main/java/com/baeldung/autowiring/service/MyServiceConfiguration.java @@ -0,0 +1,14 @@ +package com.baeldung.autowiring.service; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyServiceConfiguration { + + @Bean + MyService myService() { + return new MyService(); + } + +} diff --git a/spring-di/src/main/java/com/baeldung/methodinjections/AppConfig.java b/spring-di-3/src/main/java/com/baeldung/methodinjections/AppConfig.java similarity index 99% rename from spring-di/src/main/java/com/baeldung/methodinjections/AppConfig.java rename to spring-di-3/src/main/java/com/baeldung/methodinjections/AppConfig.java index 7c1e209383..59c0e1543a 100644 --- a/spring-di/src/main/java/com/baeldung/methodinjections/AppConfig.java +++ b/spring-di-3/src/main/java/com/baeldung/methodinjections/AppConfig.java @@ -5,6 +5,5 @@ import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = "com.baeldung.methodinjections") - public class AppConfig { } diff --git a/spring-di/src/main/java/com/baeldung/methodinjections/Grader.java b/spring-di-3/src/main/java/com/baeldung/methodinjections/Grader.java similarity index 100% rename from spring-di/src/main/java/com/baeldung/methodinjections/Grader.java rename to spring-di-3/src/main/java/com/baeldung/methodinjections/Grader.java index 10dc77484c..f1b2bc7ea4 100644 --- a/spring-di/src/main/java/com/baeldung/methodinjections/Grader.java +++ b/spring-di-3/src/main/java/com/baeldung/methodinjections/Grader.java @@ -1,9 +1,9 @@ package com.baeldung.methodinjections; -import java.util.Collection; - import org.springframework.stereotype.Component; +import java.util.Collection; + @Component public class Grader { diff --git a/spring-di/src/main/java/com/baeldung/methodinjections/SchoolNotification.java b/spring-di-3/src/main/java/com/baeldung/methodinjections/SchoolNotification.java similarity index 95% rename from spring-di/src/main/java/com/baeldung/methodinjections/SchoolNotification.java rename to spring-di-3/src/main/java/com/baeldung/methodinjections/SchoolNotification.java index 752eb8893f..d9396f09b8 100644 --- a/spring-di/src/main/java/com/baeldung/methodinjections/SchoolNotification.java +++ b/spring-di-3/src/main/java/com/baeldung/methodinjections/SchoolNotification.java @@ -1,13 +1,13 @@ package com.baeldung.methodinjections; -import java.util.ArrayList; -import java.util.Collection; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.Collection; + @Component("schoolNotification") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class SchoolNotification { @@ -19,7 +19,7 @@ public class SchoolNotification { public SchoolNotification(String name) { this.name = name; - this.marks = new ArrayList(); + this.marks = new ArrayList<>(); } public String addMark(Integer mark) { diff --git a/spring-di/src/main/java/com/baeldung/methodinjections/Student.java b/spring-di-3/src/main/java/com/baeldung/methodinjections/Student.java similarity index 100% rename from spring-di/src/main/java/com/baeldung/methodinjections/Student.java rename to spring-di-3/src/main/java/com/baeldung/methodinjections/Student.java diff --git a/spring-di/src/main/java/com/baeldung/methodinjections/StudentServices.java b/spring-di-3/src/main/java/com/baeldung/methodinjections/StudentServices.java similarity index 88% rename from spring-di/src/main/java/com/baeldung/methodinjections/StudentServices.java rename to spring-di-3/src/main/java/com/baeldung/methodinjections/StudentServices.java index 20d631b120..1bb9bda542 100644 --- a/spring-di/src/main/java/com/baeldung/methodinjections/StudentServices.java +++ b/spring-di-3/src/main/java/com/baeldung/methodinjections/StudentServices.java @@ -1,15 +1,15 @@ package com.baeldung.methodinjections; -import java.util.HashMap; -import java.util.Map; - import org.springframework.beans.factory.annotation.Lookup; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.Map; + @Component("studentService") public abstract class StudentServices { - private Map notes = new HashMap<>(); + private final Map notes = new HashMap<>(); @Lookup protected abstract SchoolNotification getNotification(String name); diff --git a/spring-di-3/src/main/resources/application.properties b/spring-di-3/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-di-3/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/spring-di/src/main/resources/beans.xml b/spring-di-3/src/main/resources/beans.xml similarity index 100% rename from spring-di/src/main/resources/beans.xml rename to spring-di-3/src/main/resources/beans.xml diff --git a/spring-di-3/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java b/spring-di-3/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java new file mode 100644 index 0000000000..3807641edd --- /dev/null +++ b/spring-di-3/src/test/java/com/baeldung/autowiring/controller/CorrectControllerIntegrationTest.java @@ -0,0 +1,23 @@ +package com.baeldung.autowiring.controller; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class CorrectControllerIntegrationTest { + + @Autowired + CorrectController controller; + + @Test + void whenControl_ThenRunSuccessfully() { + assertDoesNotThrow(() -> controller.control()); + } + +} diff --git a/spring-di-3/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java b/spring-di-3/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java new file mode 100644 index 0000000000..79d446604f --- /dev/null +++ b/spring-di-3/src/test/java/com/baeldung/autowiring/controller/FlawedControllerIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.autowiring.controller; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class FlawedControllerIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FlawedControllerIntegrationTest.class); + + @Autowired + FlawedController myController; + + @Test + void whenControl_ThenThrowNullPointerException() { + NullPointerException npe = assertThrows(NullPointerException.class, () -> myController.control()); + LOGGER.error("Got a NullPointerException", npe); + } + +} diff --git a/spring-di-3/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java b/spring-di-3/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java new file mode 100644 index 0000000000..190a7d8773 --- /dev/null +++ b/spring-di-3/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.methodinjections; + +import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class StudentIntegrationTest { + + private ConfigurableApplicationContext context; + + @AfterEach + public void tearDown() { + context.close(); + } + + @Test + public void whenLookupMethodCalled_thenNewInstanceReturned() { + context = new AnnotationConfigApplicationContext(AppConfig.class); + + Student student1 = context.getBean("studentBean", Student.class); + Student student2 = context.getBean("studentBean", Student.class); + + assertEquals(student1, student2); + assertNotEquals(student1.getNotification("Alex"), student2.getNotification("Bethany")); + } + + @Test + public void whenAbstractGetterMethodInjects_thenNewInstanceReturned() { + context = new ClassPathXmlApplicationContext("beans.xml"); + + StudentServices services = context.getBean("studentServices", StudentServices.class); + + assertEquals("PASS", services.appendMark("Alex", 76)); + assertEquals("FAIL", services.appendMark("Bethany", 44)); + assertEquals("PASS", services.appendMark("Claire", 96)); + } +} diff --git a/spring-di-3/src/test/resources/logback-test.xml b/spring-di-3/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-di-3/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-di/README.md b/spring-di/README.md index d470768f16..7b1ebd41b9 100644 --- a/spring-di/README.md +++ b/spring-di/README.md @@ -5,13 +5,10 @@ This module contains articles about dependency injection with Spring ### Relevant Articles - [The Spring @Qualifier Annotation](https://www.baeldung.com/spring-qualifier-annotation) -- [Constructor Dependency Injection in Spring](https://www.baeldung.com/constructor-injection-in-spring) - [Spring Autowiring of Generic Types](https://www.baeldung.com/spring-autowire-generics) - [Guice vs Spring – Dependency Injection](https://www.baeldung.com/guice-spring-dependency-injection) - [Injecting Prototype Beans into a Singleton Instance in Spring](https://www.baeldung.com/spring-inject-prototype-bean-into-singleton) -- [@Lookup Annotation in Spring](https://www.baeldung.com/spring-lookup) - [Controlling Bean Creation Order with @DependsOn Annotation](https://www.baeldung.com/spring-depends-on) - [Unsatisfied Dependency in Spring](https://www.baeldung.com/spring-unsatisfied-dependency) -- [Circular Dependencies in Spring](https://www.baeldung.com/circular-dependencies-in-spring) - [XML-Based Injection in Spring](https://www.baeldung.com/spring-xml-injection) -- More articles: [[next -->]](/spring-di-2) +- More articles: [[next -->]](../spring-di-2) diff --git a/spring-di/pom.xml b/spring-di/pom.xml index cbd49242e4..af0601deb6 100644 --- a/spring-di/pom.xml +++ b/spring-di/pom.xml @@ -20,14 +20,14 @@ org.springframework spring-framework-bom - ${org.springframework.version} + ${spring.version} pom import org.springframework spring-core - ${org.springframework.version} + ${spring.version} @@ -74,12 +74,6 @@ ${mockito.spring.boot.version} test - - org.assertj - assertj-core - ${assertj.version} - test - commons-io commons-io @@ -149,14 +143,11 @@ org.baeldung.org.baeldung.sample.App - 5.0.6.RELEASE 1.3.2 1.4.4.RELEASE 1 - 20.0 1.5.2.RELEASE 1.10.19 - 3.12.2 1.9.5 diff --git a/spring-di/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java b/spring-di/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java deleted file mode 100644 index 5d326a99dd..0000000000 --- a/spring-di/src/test/java/com/baeldung/methodinjections/StudentIntegrationTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.methodinjections; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -public class StudentIntegrationTest { - - @Test - public void whenLookupMethodCalled_thenNewInstanceReturned() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); - Student student1 = context.getBean("studentBean", Student.class); - Student student2 = context.getBean("studentBean", Student.class); - - Assert.assertEquals(student1, student2); - Assert.assertNotEquals(student1.getNotification("Alex"), student2.getNotification("Bethany")); - context.close(); - } - - @Test - public void whenAbstractGetterMethodInjects_thenNewInstanceReturned() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); - StudentServices services = context.getBean("studentServices", StudentServices.class); - - Assert.assertEquals("PASS", services.appendMark("Alex", 76)); - Assert.assertEquals("FAIL", services.appendMark("Bethany", 44)); - Assert.assertEquals("PASS", services.appendMark("Claire", 96)); - context.close(); - } -} diff --git a/spring-ejb/ejb-beans/pom.xml b/spring-ejb/ejb-beans/pom.xml index 10bc6d3104..6f20d949b0 100644 --- a/spring-ejb/ejb-beans/pom.xml +++ b/spring-ejb/ejb-beans/pom.xml @@ -80,12 +80,6 @@ arquillian-junit-container test - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - test - joda-time @@ -141,7 +135,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} always diff --git a/spring-ejb/pom.xml b/spring-ejb/pom.xml index 0b52fa52b1..896df6e8d8 100755 --- a/spring-ejb/pom.xml +++ b/spring-ejb/pom.xml @@ -14,20 +14,18 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - ../ spring-ejb-remote - ejb-beans spring-ejb-client wildfly - + junit junit diff --git a/spring-ejb/spring-ejb-remote/pom.xml b/spring-ejb/spring-ejb-remote/pom.xml index b7bf2aa79b..a180955dcf 100644 --- a/spring-ejb/spring-ejb-remote/pom.xml +++ b/spring-ejb/spring-ejb-remote/pom.xml @@ -19,12 +19,6 @@ javaee-api provided - - org.assertj - assertj-core - ${assertj.version} - test - @@ -86,7 +80,6 @@ - 3.9.0 1.6.1 1.1.0.Alpha5 diff --git a/spring-exceptions/pom.xml b/spring-exceptions/pom.xml index 337597a741..0621009bdd 100644 --- a/spring-exceptions/pom.xml +++ b/spring-exceptions/pom.xml @@ -169,7 +169,6 @@ 5.3.3.Final 2.2 - 19.0 4.4.5 4.5.2 2.9.0 diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml index 6f00dd5820..7cd529020a 100644 --- a/spring-jenkins-pipeline/pom.xml +++ b/spring-jenkins-pipeline/pom.xml @@ -37,7 +37,7 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo - ${de.flapdoodle.embed.mongo.version} + ${embed.mongo.version} test @@ -62,6 +62,7 @@ + org.apache.maven.plugins maven-surefire-plugin @@ -81,7 +82,7 @@ 2.17 - 3.0.0 + 3.2.6 \ No newline at end of file diff --git a/spring-jenkins-pipeline/src/test/resources/application.properties b/spring-jenkins-pipeline/src/test/resources/application.properties index 4ee830556a..bae3bfeeab 100644 --- a/spring-jenkins-pipeline/src/test/resources/application.properties +++ b/spring-jenkins-pipeline/src/test/resources/application.properties @@ -1,2 +1,4 @@ #To use a randomly allocated free port during tests to avoid port conflict across tests spring.data.mongodb.port=0 + +spring.mongodb.embedded.version=4.4.9 diff --git a/spring-jersey/pom.xml b/spring-jersey/pom.xml index 64a34074bb..197469ccf9 100644 --- a/spring-jersey/pom.xml +++ b/spring-jersey/pom.xml @@ -105,12 +105,6 @@ slf4j-jdk14 ${org.slf4j.version} - - org.assertj - assertj-core - ${assertj-core.version} - test - org.springframework.boot @@ -218,7 +212,6 @@ 4.5.5 4.0.0 2.27.2 - 3.10.0 1.5.10.RELEASE diff --git a/spring-kafka/README.md b/spring-kafka/README.md index 0be741b393..5ff3cb625b 100644 --- a/spring-kafka/README.md +++ b/spring-kafka/README.md @@ -9,6 +9,7 @@ This module contains articles about Spring with Kafka - [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag) - [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message) - [Configuring Kafka SSL Using Spring Boot](https://www.baeldung.com/spring-boot-kafka-ssl) +- [Kafka Streams With Spring Boot](https://www.baeldung.com/spring-boot-kafka-streams) ### Intro diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml index ed3767029e..d51c2e300f 100644 --- a/spring-kafka/pom.xml +++ b/spring-kafka/pom.xml @@ -19,10 +19,17 @@ org.springframework.boot spring-boot-starter + + org.springframework.boot + spring-boot-starter-web + org.springframework.kafka spring-kafka - ${spring-kafka.version} + + + org.apache.kafka + kafka-streams com.fasterxml.jackson.core @@ -35,7 +42,6 @@ org.springframework.kafka spring-kafka-test - ${spring-kafka.version} test @@ -58,8 +64,7 @@ - 2.7.2 - 1.15.3 + 1.16.2 \ No newline at end of file diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaConfig.java b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaConfig.java new file mode 100644 index 0000000000..756f46e93e --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaConfig.java @@ -0,0 +1,55 @@ +package com.baeldung.kafka.streams; + +import static org.apache.kafka.streams.StreamsConfig.APPLICATION_ID_CONFIG; +import static org.apache.kafka.streams.StreamsConfig.BOOTSTRAP_SERVERS_CONFIG; +import static org.apache.kafka.streams.StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG; +import static org.apache.kafka.streams.StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG; +import static org.apache.kafka.streams.StreamsConfig.STATE_DIR_CONFIG; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.admin.NewTopic; +import org.apache.kafka.common.serialization.Serdes; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.annotation.EnableKafkaStreams; +import org.springframework.kafka.annotation.KafkaStreamsDefaultConfiguration; +import org.springframework.kafka.config.KafkaStreamsConfiguration; +import org.springframework.kafka.config.TopicBuilder; + +@Configuration +@EnableKafka +@EnableKafkaStreams +public class KafkaConfig { + + @Value(value = "${spring.kafka.bootstrap-servers}") + private String bootstrapAddress; + + @Value(value = "${spring.kafka.streams.state.dir}") + private String stateStoreLocation; + + @Bean(name = KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME) + KafkaStreamsConfiguration kStreamsConfig() { + Map props = new HashMap<>(); + props.put(APPLICATION_ID_CONFIG, "streams-app"); + props.put(BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + props.put(DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()); + props.put(DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()); + // configure the state location to allow tests to use clean state for every run + props.put(STATE_DIR_CONFIG, stateStoreLocation); + + return new KafkaStreamsConfiguration(props); + } + + @Bean + NewTopic inputTopic() { + return TopicBuilder.name("input-topic") + .partitions(1) + .replicas(1) + .build(); + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaProducer.java b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaProducer.java new file mode 100644 index 0000000000..2b8e9bbfbd --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaProducer.java @@ -0,0 +1,23 @@ +package com.baeldung.kafka.streams; + +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Component; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@AllArgsConstructor +@Component +public class KafkaProducer { + + private final KafkaTemplate kafkaTemplate; + + public void sendMessage(String message) { + kafkaTemplate.send("input-topic", message) + .addCallback( + result -> log.info("Message sent to topic: {}", message), + ex -> log.error("Failed to send message", ex) + ); + } +} diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaStreamsApplication.java b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaStreamsApplication.java new file mode 100644 index 0000000000..7ecc59ea69 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/streams/KafkaStreamsApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.kafka.streams; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class KafkaStreamsApplication { + + public static void main(String[] args) { + SpringApplication.run(KafkaStreamsApplication.class, args); + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountProcessor.java b/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountProcessor.java new file mode 100644 index 0000000000..2a49b79b1e --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountProcessor.java @@ -0,0 +1,36 @@ +package com.baeldung.kafka.streams; + +import java.util.Arrays; + +import org.apache.kafka.common.serialization.Serde; +import org.apache.kafka.common.serialization.Serdes; +import org.apache.kafka.streams.StreamsBuilder; +import org.apache.kafka.streams.kstream.Consumed; +import org.apache.kafka.streams.kstream.Grouped; +import org.apache.kafka.streams.kstream.KStream; +import org.apache.kafka.streams.kstream.KTable; +import org.apache.kafka.streams.kstream.Materialized; +import org.apache.kafka.streams.kstream.ValueMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class WordCountProcessor { + + private static final Serde STRING_SERDE = Serdes.String(); + + @Autowired + void buildPipeline(StreamsBuilder streamsBuilder) { + KStream messageStream = streamsBuilder + .stream("input-topic", Consumed.with(STRING_SERDE, STRING_SERDE)); + + KTable wordCounts = messageStream + .mapValues((ValueMapper) String::toLowerCase) + .flatMapValues(value -> Arrays.asList(value.split("\\W+"))) + .groupBy((key, word) -> word, Grouped.with(STRING_SERDE, STRING_SERDE)) + .count(Materialized.as("counts")); + + wordCounts.toStream().to("output-topic"); + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountRestService.java b/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountRestService.java new file mode 100644 index 0000000000..df63b51749 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/streams/WordCountRestService.java @@ -0,0 +1,36 @@ +package com.baeldung.kafka.streams; + +import org.apache.kafka.streams.KafkaStreams; +import org.apache.kafka.streams.StoreQueryParameters; +import org.apache.kafka.streams.state.QueryableStoreTypes; +import org.apache.kafka.streams.state.ReadOnlyKeyValueStore; +import org.springframework.kafka.config.StreamsBuilderFactoryBean; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +public class WordCountRestService { + + private final StreamsBuilderFactoryBean factoryBean; + + private final KafkaProducer kafkaProducer; + + @GetMapping("/count/{word}") + public Long getWordCount(@PathVariable String word) { + KafkaStreams kafkaStreams = factoryBean.getKafkaStreams(); + ReadOnlyKeyValueStore counts = kafkaStreams + .store(StoreQueryParameters.fromNameAndType("counts", QueryableStoreTypes.keyValueStore())); + return counts.get(word); + } + + @PostMapping("/message") + public void addMessage(@RequestBody String message) { + kafkaProducer.sendMessage(message); + } +} diff --git a/spring-kafka/src/test/java/com/baeldung/kafka/streams/KafkaStreamsApplicationLiveTest.java b/spring-kafka/src/test/java/com/baeldung/kafka/streams/KafkaStreamsApplicationLiveTest.java new file mode 100644 index 0000000000..85df8485d2 --- /dev/null +++ b/spring-kafka/src/test/java/com/baeldung/kafka/streams/KafkaStreamsApplicationLiveTest.java @@ -0,0 +1,143 @@ +package com.baeldung.kafka.streams; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.*; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.LongDeserializer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Testcontainers +@SpringBootTest(classes = KafkaStreamsApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) +class KafkaStreamsApplicationLiveTest { + + private final BlockingQueue output = new LinkedBlockingQueue<>(); + + @Container + private static final KafkaContainer KAFKA = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3")); + + @TempDir + private static File tempDir; + + private KafkaMessageListenerContainer consumer; + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @BeforeEach + public void setUp() { + output.clear(); + createConsumer(); + } + + @Test + void givenInputMessages_whenPostToEndpoint_thenWordCountsReceivedOnOutput() throws Exception { + postMessage("test message"); + + startOutputTopicConsumer(); + + // assert correct counts from output topic + assertThat(output.poll(2, MINUTES)).isEqualTo("test:1"); + assertThat(output.poll(2, MINUTES)).isEqualTo("message:1"); + + // assert correct count from REST service + assertThat(getCountFromRestServiceFor("test")).isEqualTo(1); + assertThat(getCountFromRestServiceFor("message")).isEqualTo(1); + + postMessage("another test message"); + + // assert correct counts from output topic + assertThat(output.poll(2, MINUTES)).isEqualTo("another:1"); + assertThat(output.poll(2, MINUTES)).isEqualTo("test:2"); + assertThat(output.poll(2, MINUTES)).isEqualTo("message:2"); + + // assert correct count from REST service + assertThat(getCountFromRestServiceFor("another")).isEqualTo(1); + assertThat(getCountFromRestServiceFor("test")).isEqualTo(2); + assertThat(getCountFromRestServiceFor("message")).isEqualTo(2); + } + + private void postMessage(String message) { + HttpEntity request = new HttpEntity<>(message, new HttpHeaders()); + restTemplate.postForEntity(createURLWithPort("/message"), request, null); + } + + private int getCountFromRestServiceFor(String word) { + HttpEntity entity = new HttpEntity<>(null, new HttpHeaders()); + ResponseEntity response = restTemplate.exchange( + createURLWithPort("/count/" + word), + HttpMethod.GET, entity, String.class + ); + return Integer.parseInt(Objects.requireNonNull(response.getBody())); + } + + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } + + private void createConsumer() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA.getBootstrapServers()); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "baeldung"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class); + + // set up the consumer for the word count output + DefaultKafkaConsumerFactory cf = new DefaultKafkaConsumerFactory<>(props); + ContainerProperties containerProperties = new ContainerProperties("output-topic"); + consumer = new KafkaMessageListenerContainer<>(cf, containerProperties); + consumer.setBeanName("templateTests"); + + consumer.setupMessageListener((MessageListener) record -> { + log.info("Record received: {}", record); + output.add(record.key() + ":" + record.value()); + }); + } + + private void startOutputTopicConsumer() { + consumer.start(); + } + + @DynamicPropertySource + static void registerKafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", KAFKA::getBootstrapServers); + registry.add("spring.kafka.streams.state.dir", tempDir::getAbsolutePath); + } + +} diff --git a/spring-kafka/src/test/java/com/baeldung/kafka/streams/WordCountProcessorUnitTest.java b/spring-kafka/src/test/java/com/baeldung/kafka/streams/WordCountProcessorUnitTest.java new file mode 100644 index 0000000000..216226a566 --- /dev/null +++ b/spring-kafka/src/test/java/com/baeldung/kafka/streams/WordCountProcessorUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.kafka.streams; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Properties; + +import org.apache.kafka.common.serialization.LongDeserializer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.apache.kafka.streams.KeyValue; +import org.apache.kafka.streams.StreamsBuilder; +import org.apache.kafka.streams.TestInputTopic; +import org.apache.kafka.streams.TestOutputTopic; +import org.apache.kafka.streams.Topology; +import org.apache.kafka.streams.TopologyTestDriver; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class WordCountProcessorUnitTest { + + private WordCountProcessor wordCountProcessor; + + @BeforeEach + void setUp() { + wordCountProcessor = new WordCountProcessor(); + } + + @Test + void givenInputMessages_whenProcessed_thenWordCountIsProduced() { + StreamsBuilder streamsBuilder = new StreamsBuilder(); + wordCountProcessor.buildPipeline(streamsBuilder); + Topology topology = streamsBuilder.build(); + + try (TopologyTestDriver topologyTestDriver = new TopologyTestDriver(topology, new Properties())) { + + TestInputTopic inputTopic = topologyTestDriver + .createInputTopic("input-topic", new StringSerializer(), new StringSerializer()); + + TestOutputTopic outputTopic = topologyTestDriver + .createOutputTopic("output-topic", new StringDeserializer(), new LongDeserializer()); + + inputTopic.pipeInput("key", "hello world"); + inputTopic.pipeInput("key2", "hello"); + + assertThat(outputTopic.readKeyValuesToList()) + .containsExactly( + KeyValue.pair("hello", 1L), + KeyValue.pair("world", 1L), + KeyValue.pair("hello", 2L) + ); + } + } + +} diff --git a/spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks b/spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks index 62ddfe199d..e23c569619 100644 Binary files a/spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks and b/spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks differ diff --git a/spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks b/spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks index 2b07327b13..f35facf7e0 100644 Binary files a/spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks and b/spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks differ diff --git a/spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks b/spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks index c038ad86b9..c3408d5be3 100644 Binary files a/spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks and b/spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks differ diff --git a/spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks b/spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks index 1ec806b50d..d5931f8995 100644 Binary files a/spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks and b/spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks differ diff --git a/spring-kafka/src/test/resources/docker/docker-compose.yml b/spring-kafka/src/test/resources/docker/docker-compose.yml index d65dd58b19..ae0e2d538c 100644 --- a/spring-kafka/src/test/resources/docker/docker-compose.yml +++ b/spring-kafka/src/test/resources/docker/docker-compose.yml @@ -12,8 +12,8 @@ services: depends_on: - zookeeper ports: - - 9092:9092 - - 9093:9093 + - "9092:9092" + - "9093:9093" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 diff --git a/spring-mockito/pom.xml b/spring-mockito/pom.xml index 0753935d0c..e0d7bee6f3 100644 --- a/spring-mockito/pom.xml +++ b/spring-mockito/pom.xml @@ -28,8 +28,4 @@ - - 2.24.0 - - \ No newline at end of file diff --git a/spring-quartz/pom.xml b/spring-quartz/pom.xml index 19ea302a1d..e8919bfadb 100644 --- a/spring-quartz/pom.xml +++ b/spring-quartz/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-quartz - spring-quartz 0.0.1-SNAPSHOT + spring-quartz jar Demo project for Scheduling in Spring with Quartz @@ -54,8 +54,8 @@ - 2.3.0 - 0.9.5.2 + 2.3.2 + 0.9.5.5 \ No newline at end of file diff --git a/spring-quartz/src/main/resources/application.properties b/spring-quartz/src/main/resources/application.properties index 557349af2e..ffe90aadd5 100644 --- a/spring-quartz/src/main/resources/application.properties +++ b/spring-quartz/src/main/resources/application.properties @@ -2,7 +2,7 @@ using.spring.schedulerFactory=true spring.quartz.job-store-type=jdbc # Always create the Quartz database on startup -spring.quartz.jdbc.initialize-schema=always +spring.quartz.jdbc.initialize-schema=never spring.datasource.jdbc-url=jdbc:h2:mem:spring-quartz;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver diff --git a/spring-quartz/src/main/resources/quartz.properties b/spring-quartz/src/main/resources/quartz.properties index 662bb83eb0..8cecd7d3d3 100644 --- a/spring-quartz/src/main/resources/quartz.properties +++ b/spring-quartz/src/main/resources/quartz.properties @@ -20,3 +20,4 @@ org.quartz.dataSource.quartzDataSource.URL=jdbc:h2:mem:spring-quartz;INIT=RUNSCR org.quartz.dataSource.quartzDataSource.driver=org.h2.Driver org.quartz.dataSource.quartzDataSource.user=sa org.quartz.dataSource.quartzDataSource.password= +org.quartz.jdbc.initialize-schema=never diff --git a/spring-reactive/README.md b/spring-reactive/README.md new file mode 100644 index 0000000000..9f1852d912 --- /dev/null +++ b/spring-reactive/README.md @@ -0,0 +1,16 @@ +## Spring Reactive + +This module contains articles describing reactive processing in Spring. + +## Relevant articles: + +- [Intro To Reactor Core](https://www.baeldung.com/reactor-core) +- [Debugging Reactive Streams in Java](https://www.baeldung.com/spring-debugging-reactive-streams) +- [Guide to Spring 5 WebFlux](https://www.baeldung.com/spring-webflux) +- [Introduction to the Functional Web Framework in Spring 5](https://www.baeldung.com/spring-5-functional-web) +- [Spring 5 WebClient](https://www.baeldung.com/spring-5-webclient) +- [Spring WebClient vs. RestTemplate](https://www.baeldung.com/spring-webclient-resttemplate) +- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters) +- [Handling Errors in Spring WebFlux](https://www.baeldung.com/spring-webflux-errors) +- [Spring Security 5 for Reactive Applications](https://www.baeldung.com/spring-security-5-reactive) +- [Concurrency in Spring WebFlux](https://www.baeldung.com/spring-webflux-concurrency) \ No newline at end of file diff --git a/spring-reactive/pom.xml b/spring-reactive/pom.xml new file mode 100644 index 0000000000..d31ee04d82 --- /dev/null +++ b/spring-reactive/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + spring-reactive + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + io.reactivex.rxjava2 + rxjava + ${rxjava.version} + + + io.projectreactor.kafka + reactor-kafka + ${reactor-kafka.version} + + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + + + org.springframework.security + spring-security-test + test + + + io.projectreactor + reactor-test + ${reactor.version} + test + + + org.projectlombok + lombok + + + + + + integration-lite-first + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + integration-lite-second + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + + + + + + 3.4.12 + 1.2.2.RELEASE + 2.2.19 + + + \ No newline at end of file diff --git a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Application.java b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Application.java similarity index 92% rename from spring-webflux-threads/src/main/java/com/baeldung/webflux/Application.java rename to spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Application.java index 06a148a77f..f34d930ef0 100644 --- a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Application.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Application.java @@ -1,4 +1,4 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.concurrency; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Controller.java b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Controller.java similarity index 99% rename from spring-webflux-threads/src/main/java/com/baeldung/webflux/Controller.java rename to spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Controller.java index 3c7e4e41ca..70928d4dca 100644 --- a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Controller.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Controller.java @@ -1,12 +1,6 @@ -package com.baeldung.webflux; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +package com.baeldung.reactive.concurrency; +import io.reactivex.Observable; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; @@ -21,8 +15,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; - -import io.reactivex.Observable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @@ -34,6 +26,13 @@ import reactor.kafka.sender.KafkaSender; import reactor.kafka.sender.SenderOptions; import reactor.kafka.sender.SenderRecord; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + @RestController @RequestMapping("/") public class Controller { diff --git a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Person.java b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Person.java similarity index 91% rename from spring-webflux-threads/src/main/java/com/baeldung/webflux/Person.java rename to spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Person.java index 4c6bd5f585..10029330af 100644 --- a/spring-webflux-threads/src/main/java/com/baeldung/webflux/Person.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/Person.java @@ -1,4 +1,4 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.concurrency; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; diff --git a/spring-webflux-threads/src/main/java/com/baeldung/webflux/PersonRepository.java b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/PersonRepository.java similarity index 79% rename from spring-webflux-threads/src/main/java/com/baeldung/webflux/PersonRepository.java rename to spring-reactive/src/main/java/com/baeldung/reactive/concurrency/PersonRepository.java index 38fbd3d431..221ea3d74d 100644 --- a/spring-webflux-threads/src/main/java/com/baeldung/webflux/PersonRepository.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/concurrency/PersonRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.concurrency; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/ConsumerDebuggingApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/ConsumerDebuggingApplication.java similarity index 96% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/ConsumerDebuggingApplication.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/ConsumerDebuggingApplication.java index 3f01310006..fa10383c95 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/ConsumerDebuggingApplication.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/ConsumerDebuggingApplication.java @@ -1,6 +1,4 @@ -package com.baeldung.debugging.consumer; - -import java.util.Collections; +package com.baeldung.reactive.debugging.consumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -9,9 +7,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; - import reactor.core.publisher.Hooks; +import java.util.Collections; + @SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) @EnableScheduling public class ConsumerDebuggingApplication { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/chronjobs/ChronJobs.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/chronjobs/ChronJobs.java similarity index 95% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/chronjobs/ChronJobs.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/chronjobs/ChronJobs.java index bf96ab56d6..b58648ff9d 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/chronjobs/ChronJobs.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/chronjobs/ChronJobs.java @@ -1,8 +1,8 @@ -package com.baeldung.debugging.consumer.chronjobs; - -import java.time.Duration; -import java.util.concurrent.ThreadLocalRandom; +package com.baeldung.reactive.debugging.consumer.chronjobs; +import com.baeldung.reactive.debugging.consumer.model.Foo; +import com.baeldung.reactive.debugging.consumer.model.FooDto; +import com.baeldung.reactive.debugging.consumer.service.FooService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,13 +10,11 @@ import org.springframework.http.MediaType; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; - -import com.baeldung.debugging.consumer.model.Foo; -import com.baeldung.debugging.consumer.model.FooDto; -import com.baeldung.debugging.consumer.service.FooService; - import reactor.core.publisher.Flux; +import java.time.Duration; +import java.util.concurrent.ThreadLocalRandom; + @Component public class ChronJobs { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java similarity index 89% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java index 3dcdc6c7c0..df13113a82 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/controllers/ReactiveConfigsToggleRestController.java @@ -1,8 +1,7 @@ -package com.baeldung.debugging.consumer.controllers; +package com.baeldung.reactive.debugging.consumer.controllers; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; - import reactor.core.publisher.Hooks; @RestController diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/Foo.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/Foo.java similarity index 91% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/Foo.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/Foo.java index 916ca93bfc..d20e2c9ba0 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/Foo.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/Foo.java @@ -1,12 +1,12 @@ -package com.baeldung.debugging.consumer.model; - -import java.util.concurrent.ThreadLocalRandom; +package com.baeldung.reactive.debugging.consumer.model; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.concurrent.ThreadLocalRandom; + @Getter @Setter @NoArgsConstructor diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/FooDto.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/FooDto.java similarity index 81% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/FooDto.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/FooDto.java index 33f19c4e60..bf6f614e18 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/model/FooDto.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/model/FooDto.java @@ -1,4 +1,4 @@ -package com.baeldung.debugging.consumer.model; +package com.baeldung.reactive.debugging.consumer.model; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooNameHelper.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooNameHelper.java similarity index 91% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooNameHelper.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooNameHelper.java index 772b360437..cdd9ca31a6 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooNameHelper.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooNameHelper.java @@ -1,11 +1,10 @@ -package com.baeldung.debugging.consumer.service; +package com.baeldung.reactive.debugging.consumer.service; + +import com.baeldung.reactive.debugging.consumer.model.Foo; +import reactor.core.publisher.Flux; import java.util.concurrent.ThreadLocalRandom; -import com.baeldung.debugging.consumer.model.Foo; - -import reactor.core.publisher.Flux; - public class FooNameHelper { public static Flux concatAndSubstringFooName(Flux flux) { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooQuantityHelper.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooQuantityHelper.java similarity index 86% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooQuantityHelper.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooQuantityHelper.java index 615239313d..f4600b41b9 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooQuantityHelper.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooQuantityHelper.java @@ -1,11 +1,10 @@ -package com.baeldung.debugging.consumer.service; +package com.baeldung.reactive.debugging.consumer.service; + +import com.baeldung.reactive.debugging.consumer.model.Foo; +import reactor.core.publisher.Flux; import java.util.concurrent.ThreadLocalRandom; -import com.baeldung.debugging.consumer.model.Foo; - -import reactor.core.publisher.Flux; - public class FooQuantityHelper { public static Flux processFooReducingQuantity(Flux flux) { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooReporter.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooReporter.java similarity index 86% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooReporter.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooReporter.java index f53cd238e0..1a8f9bc783 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooReporter.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooReporter.java @@ -1,10 +1,8 @@ -package com.baeldung.debugging.consumer.service; +package com.baeldung.reactive.debugging.consumer.service; +import com.baeldung.reactive.debugging.consumer.model.Foo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.baeldung.debugging.consumer.model.Foo; - import reactor.core.publisher.Flux; public class FooReporter { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooService.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooService.java similarity index 87% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooService.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooService.java index 438f6d473c..bafaa3cfa0 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/consumer/service/FooService.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/consumer/service/FooService.java @@ -1,20 +1,18 @@ -package com.baeldung.debugging.consumer.service; - -import static com.baeldung.debugging.consumer.service.FooNameHelper.concatAndSubstringFooName; -import static com.baeldung.debugging.consumer.service.FooNameHelper.substringFooName; -import static com.baeldung.debugging.consumer.service.FooQuantityHelper.divideFooQuantity; -import static com.baeldung.debugging.consumer.service.FooQuantityHelper.processFooReducingQuantity; -import static com.baeldung.debugging.consumer.service.FooReporter.reportResult; +package com.baeldung.reactive.debugging.consumer.service; +import com.baeldung.reactive.debugging.consumer.model.Foo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; - -import com.baeldung.debugging.consumer.model.Foo; - import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; +import static com.baeldung.reactive.debugging.consumer.service.FooNameHelper.concatAndSubstringFooName; +import static com.baeldung.reactive.debugging.consumer.service.FooNameHelper.substringFooName; +import static com.baeldung.reactive.debugging.consumer.service.FooQuantityHelper.divideFooQuantity; +import static com.baeldung.reactive.debugging.consumer.service.FooQuantityHelper.processFooReducingQuantity; +import static com.baeldung.reactive.debugging.consumer.service.FooReporter.reportResult; + @Component public class FooService { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/ServerDebuggingApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/ServerDebuggingApplication.java similarity index 82% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/ServerDebuggingApplication.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/ServerDebuggingApplication.java index 4fdc1dd137..ddf97ee5a8 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/ServerDebuggingApplication.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/ServerDebuggingApplication.java @@ -1,16 +1,17 @@ -package com.baeldung.debugging.server; - -import java.util.Collections; +package com.baeldung.reactive.debugging.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.web.reactive.config.EnableWebFlux; +import java.util.Collections; + @EnableWebFlux -@SpringBootApplication +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) public class ServerDebuggingApplication { public static void main(String[] args) { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/handlers/ServerHandler.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/handlers/ServerHandler.java similarity index 93% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/handlers/ServerHandler.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/handlers/ServerHandler.java index 759cd9b01d..15f9a4b786 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/handlers/ServerHandler.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/handlers/ServerHandler.java @@ -1,20 +1,18 @@ -package com.baeldung.debugging.server.handlers; - -import java.time.Duration; -import java.util.concurrent.ThreadLocalRandom; +package com.baeldung.reactive.debugging.server.handlers; +import com.baeldung.reactive.debugging.server.model.Foo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; - -import com.baeldung.debugging.server.model.Foo; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.util.concurrent.ThreadLocalRandom; + @Component public class ServerHandler { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/model/Foo.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/model/Foo.java similarity index 73% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/model/Foo.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/model/Foo.java index 2d9491f3dd..2c419a23f8 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/model/Foo.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/model/Foo.java @@ -1,4 +1,4 @@ -package com.baeldung.debugging.server.model; +package com.baeldung.reactive.debugging.server.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/routers/ServerRouter.java b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/routers/ServerRouter.java similarity index 86% rename from spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/routers/ServerRouter.java rename to spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/routers/ServerRouter.java index 6378b2213d..5db2ab92b6 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/debugging/server/routers/ServerRouter.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/debugging/server/routers/ServerRouter.java @@ -1,5 +1,6 @@ -package com.baeldung.debugging.server.routers; +package com.baeldung.reactive.debugging.server.routers; +import com.baeldung.reactive.debugging.server.handlers.ServerHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -8,8 +9,6 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; -import com.baeldung.debugging.server.handlers.ServerHandler; - @Configuration public class ServerRouter { diff --git a/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/ErrorHandlingApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/ErrorHandlingApplication.java new file mode 100644 index 0000000000..c40db74003 --- /dev/null +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/ErrorHandlingApplication.java @@ -0,0 +1,25 @@ +package com.baeldung.reactive.errorhandling; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) +public class ErrorHandlingApplication { + + public static void main(String[] args) { + SpringApplication.run(ErrorHandlingApplication.class, args); + } + + @Bean + public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .permitAll(); + http.csrf().disable(); + return http.build(); + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java index 5885ac50d0..0a96a8593c 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java @@ -1,14 +1,13 @@ - package com.baeldung.reactive.errorhandling; -import java.util.Map; - import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.reactive.error.DefaultErrorAttributes; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.ServerRequest; +import java.util.Map; + @Component public class GlobalErrorAttributes extends DefaultErrorAttributes{ diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java similarity index 97% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java index 4f3f1795da..24583308cd 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java @@ -1,8 +1,5 @@ - package com.baeldung.reactive.errorhandling; -import java.util.Map; - import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler; import org.springframework.boot.web.error.ErrorAttributeOptions; @@ -19,14 +16,15 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; - import reactor.core.publisher.Mono; +import java.util.Map; + @Component @Order(-2) public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { - public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext, + public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) { super(g, new WebProperties.Resources(), applicationContext); super.setMessageWriters(serverCodecConfigurer.getWriters()); diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java index 38d35544a7..bdc7771b80 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling; import org.springframework.http.HttpStatus; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java index c71c8ecac0..32f2f1c3a2 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.handlers; import org.springframework.http.MediaType; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java index 92e881543e..093120c92b 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.handlers; import org.springframework.http.MediaType; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java index 8c988a6633..44842e0539 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.handlers; import org.springframework.http.MediaType; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java index 3d6ef258d3..2d391a42a7 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.handlers; import com.baeldung.reactive.errorhandling.NameRequiredException; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java index 41605b355b..a466982865 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.handlers; import org.springframework.stereotype.Component; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java index 91be24571c..caf779b456 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.routers; import com.baeldung.reactive.errorhandling.handlers.Handler1; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java index bc7831f494..b965257c30 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.routers; import com.baeldung.reactive.errorhandling.handlers.Handler2; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java index 461e6fe9e7..b8f7f983cc 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.routers; import com.baeldung.reactive.errorhandling.handlers.Handler3; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java index 9dccc6858f..03c65fec67 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.routers; import com.baeldung.reactive.errorhandling.handlers.Handler4; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java similarity index 99% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java rename to spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java index 59fd587fc8..c68e04659f 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java @@ -1,4 +1,3 @@ - package com.baeldung.reactive.errorhandling.routers; import com.baeldung.reactive.errorhandling.handlers.Handler5; diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/GreetController.java b/spring-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java similarity index 100% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/GreetController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/GreetService.java b/spring-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java similarity index 100% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/GreetService.java rename to spring-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java b/spring-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java similarity index 88% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java rename to spring-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java index 64e96ddae1..bb2f2d50e1 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java @@ -1,6 +1,5 @@ package com.baeldung.reactive.security; -import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; @@ -12,8 +11,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.server.SecurityWebFilterChain; -import com.baeldung.reactive.actuator.FeaturesEndpoint; - @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig { @@ -23,8 +20,6 @@ public class SecurityConfig { return http.authorizeExchange() .pathMatchers("/admin") .hasAuthority("ROLE_ADMIN") - .matchers(EndpointRequest.to(FeaturesEndpoint.class)) - .permitAll() .anyExchange() .authenticated() .and() diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java b/spring-reactive/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java similarity index 99% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java rename to spring-reactive/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java index bb0f007ada..bc0895a38b 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java @@ -8,7 +8,6 @@ import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; import org.springframework.web.reactive.config.EnableWebFlux; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; - import reactor.netty.DisposableServer; import reactor.netty.http.server.HttpServer; diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/Foo.java similarity index 87% rename from spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/Foo.java index c6e3678832..a58d672686 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/Foo.java @@ -1,4 +1,4 @@ -package com.baeldung.web.reactive.client; +package com.baeldung.reactive.webclient; public class Foo { diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/Tweet.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/Tweet.java similarity index 83% rename from spring-5-reactive-2/src/main/java/com/baeldung/webclient/Tweet.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/Tweet.java index 8d294955f3..4ef1aecabb 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/Tweet.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/Tweet.java @@ -1,4 +1,4 @@ -package com.baeldung.webclient; +package com.baeldung.reactive.webclient; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/TweetsSlowServiceController.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/TweetsSlowServiceController.java similarity index 93% rename from spring-5-reactive-2/src/main/java/com/baeldung/webclient/TweetsSlowServiceController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/TweetsSlowServiceController.java index fecaca25ef..42ff603b87 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/TweetsSlowServiceController.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/TweetsSlowServiceController.java @@ -1,4 +1,4 @@ -package com.baeldung.webclient; +package com.baeldung.reactive.webclient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebClientApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientApplication.java similarity index 72% rename from spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebClientApplication.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientApplication.java index 3c53a2c1d3..fd1cb8aff1 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebClientApplication.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientApplication.java @@ -1,22 +1,24 @@ -package com.baeldung.webclient; +package com.baeldung.reactive.webclient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; -@SpringBootApplication +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) public class WebClientApplication { + public static void main(String[] args) { SpringApplication.run(WebClientApplication.class, args); } - + @Bean public SecurityWebFilterChain functionalValidationsSpringSecurityFilterChain(ServerHttpSecurity http) { http.authorizeExchange() - .anyExchange() - .permitAll(); + .anyExchange() + .permitAll(); http.csrf().disable(); return http.build(); } diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientController.java similarity index 93% rename from spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientController.java index 1a91001807..0a83b1a1b7 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebClientController.java @@ -1,7 +1,4 @@ -package com.baeldung.web.reactive.client; - -import java.util.HashMap; -import java.util.Map; +package com.baeldung.reactive.webclient; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -11,9 +8,11 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; - import reactor.core.publisher.Mono; +import java.util.HashMap; +import java.util.Map; + @RestController public class WebClientController { @@ -37,6 +36,6 @@ public class WebClientController { @PostMapping(value = "/resource-multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public String handleFormUpload(@RequestPart("key1") String value1, @RequestPart("key2") String value2) { - return "processed-" + value1 + "-" + value2; + return "processed-" + value1 + '-' + value2; } } diff --git a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebController.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebController.java similarity index 97% rename from spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebController.java index 73f5724819..30b3ccc959 100644 --- a/spring-5-reactive-2/src/main/java/com/baeldung/webclient/WebController.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclient/WebController.java @@ -1,4 +1,4 @@ -package com.baeldung.webclient; +package com.baeldung.reactive.webclient; import lombok.Setter; import lombok.extern.slf4j.Slf4j; diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java b/spring-reactive/src/main/java/com/baeldung/reactive/webclientrequests/SpringWebClientRequestsApp.java similarity index 58% rename from spring-5-webflux/src/main/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webclientrequests/SpringWebClientRequestsApp.java index 314fe2fdf9..e16c3fe551 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webclientrequests/SpringWebClientRequestsApp.java @@ -1,9 +1,10 @@ -package com.baeldung.spring.webclientrequests; +package com.baeldung.reactive.webclientrequests; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; -@SpringBootApplication +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) public class SpringWebClientRequestsApp { public static void main(String[] args) { diff --git a/spring-reactive/src/main/java/com/baeldung/reactive/webflux/Employee.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/Employee.java new file mode 100644 index 0000000000..d41a4f2791 --- /dev/null +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/Employee.java @@ -0,0 +1,17 @@ +package com.baeldung.reactive.webflux; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Employee { + + private String id; + private String name; + + // standard getters and setters + +} diff --git a/spring-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeRepository.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeRepository.java new file mode 100644 index 0000000000..9aebc577b0 --- /dev/null +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeRepository.java @@ -0,0 +1,58 @@ +package com.baeldung.reactive.webflux; + +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.Map; + +@Repository +public class EmployeeRepository { + + static Map employeeData; + + static Map employeeAccessData; + + static { + employeeData = new HashMap<>(); + employeeData.put("1", new Employee("1", "Employee 1")); + employeeData.put("2", new Employee("2", "Employee 2")); + employeeData.put("3", new Employee("3", "Employee 3")); + employeeData.put("4", new Employee("4", "Employee 4")); + employeeData.put("5", new Employee("5", "Employee 5")); + employeeData.put("6", new Employee("6", "Employee 6")); + employeeData.put("7", new Employee("7", "Employee 7")); + employeeData.put("8", new Employee("8", "Employee 8")); + employeeData.put("9", new Employee("9", "Employee 9")); + employeeData.put("10", new Employee("10", "Employee 10")); + + employeeAccessData = new HashMap<>(); + employeeAccessData.put("1", "Employee 1 Access Key"); + employeeAccessData.put("2", "Employee 2 Access Key"); + employeeAccessData.put("3", "Employee 3 Access Key"); + employeeAccessData.put("4", "Employee 4 Access Key"); + employeeAccessData.put("5", "Employee 5 Access Key"); + employeeAccessData.put("6", "Employee 6 Access Key"); + employeeAccessData.put("7", "Employee 7 Access Key"); + employeeAccessData.put("8", "Employee 8 Access Key"); + employeeAccessData.put("9", "Employee 9 Access Key"); + employeeAccessData.put("10", "Employee 10 Access Key"); + } + + public Mono findEmployeeById(String id) { + return Mono.just(employeeData.get(id)); + } + + public Flux findAllEmployees() { + return Flux.fromIterable(employeeData.values()); + } + + public Mono updateEmployee(Employee employee) { + Employee existingEmployee = employeeData.get(employee.getId()); + if (existingEmployee != null) { + existingEmployee.setName(employee.getName()); + } + return Mono.just(existingEmployee); + } +} diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeController.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeController.java similarity index 84% rename from spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeController.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeController.java index 34e44afc8b..23aacfdd95 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeController.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeController.java @@ -1,12 +1,13 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.webflux.annotation; +import com.baeldung.reactive.webflux.Employee; +import com.baeldung.reactive.webflux.EmployeeRepository; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -14,7 +15,7 @@ import reactor.core.publisher.Mono; @RequestMapping("/employees") public class EmployeeController { - private EmployeeRepository employeeRepository; + private final EmployeeRepository employeeRepository; public EmployeeController(EmployeeRepository employeeRepository) { this.employeeRepository = employeeRepository; diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeSpringApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeSpringApplication.java similarity index 65% rename from spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeSpringApplication.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeSpringApplication.java index 2652c36695..f1d21bdc77 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeSpringApplication.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeSpringApplication.java @@ -1,13 +1,13 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.webflux.annotation; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; -@SpringBootApplication +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) public class EmployeeSpringApplication { public static void main(String[] args) { - SpringApplication.run(EmployeeSpringApplication.class, args); EmployeeWebClient employeeWebClient = new EmployeeWebClient(); diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebClient.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebClient.java similarity index 59% rename from spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebClient.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebClient.java index eb32408a7f..611a261a1b 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebClient.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebClient.java @@ -1,12 +1,16 @@ -package com.baeldung.webflux; +package com.baeldung.reactive.webflux.annotation; +import com.baeldung.reactive.webflux.Employee; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.web.reactive.function.client.WebClient; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public class EmployeeWebClient { + private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeWebClient.class); + WebClient client = WebClient.create("http://localhost:8080"); public void consume() { @@ -16,13 +20,13 @@ public class EmployeeWebClient { .retrieve() .bodyToMono(Employee.class); - employeeMono.subscribe(System.out::println); + employeeMono.subscribe(employee -> LOGGER.debug("Employee: {}", employee)); Flux employeeFlux = client.get() .uri("/employees") .retrieve() .bodyToFlux(Employee.class); - employeeFlux.subscribe(System.out::println); + employeeFlux.subscribe(employee -> LOGGER.debug("Employee: {}", employee)); } } \ No newline at end of file diff --git a/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebSecurityConfig.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebSecurityConfig.java new file mode 100644 index 0000000000..8dfa455ce3 --- /dev/null +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/annotation/EmployeeWebSecurityConfig.java @@ -0,0 +1,45 @@ +package com.baeldung.reactive.webflux.annotation; + +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@EnableWebFluxSecurity +public class EmployeeWebSecurityConfig { + + @Bean + public MapReactiveUserDetailsService userDetailsService() { + UserDetails user = User + .withUsername("admin") + .password(passwordEncoder().encode("password")) + .roles("ADMIN") + .build(); + return new MapReactiveUserDetailsService(user); + } + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.csrf() + .disable() + .authorizeExchange() + .pathMatchers(HttpMethod.POST, "/employees/update") + .hasRole("ADMIN") + .pathMatchers("/**") + .permitAll() + .and() + .httpBasic(); + return http.build(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeFunctionalConfig.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeFunctionalConfig.java similarity index 92% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeFunctionalConfig.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeFunctionalConfig.java index 76b697c1aa..f97d40e4e7 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeFunctionalConfig.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeFunctionalConfig.java @@ -1,75 +1,74 @@ -package com.baeldung.reactive.functional; - -import static org.springframework.web.reactive.function.BodyExtractors.toMono; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.ServerResponse; - -import com.baeldung.webflux.Employee; -import com.baeldung.webflux.EmployeeRepository; - -@Configuration -public class EmployeeFunctionalConfig { - - @Bean - EmployeeRepository employeeRepository() { - return new EmployeeRepository(); - } - - @Bean - RouterFunction getAllEmployeesRoute() { - return route(GET("/employees"), - req -> ok().body( - employeeRepository().findAllEmployees(), Employee.class)); - } - - @Bean - RouterFunction getEmployeeByIdRoute() { - return route(GET("/employees/{id}"), - req -> ok().body( - employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)); - } - - @Bean - RouterFunction updateEmployeeRoute() { - return route(POST("/employees/update"), - req -> req.body(toMono(Employee.class)) - .doOnNext(employeeRepository()::updateEmployee) - .then(ok().build())); - } - - @Bean - RouterFunction composedRoutes() { - return - route(GET("/employees"), - req -> ok().body( - employeeRepository().findAllEmployees(), Employee.class)) - - .and(route(GET("/employees/{id}"), - req -> ok().body( - employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class))) - - .and(route(POST("/employees/update"), - req -> req.body(toMono(Employee.class)) - .doOnNext(employeeRepository()::updateEmployee) - .then(ok().build()))); - } - - @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.csrf() - .disable() - .authorizeExchange() - .anyExchange() - .permitAll(); - return http.build(); - } -} +package com.baeldung.reactive.webflux.functional; + +import com.baeldung.reactive.webflux.Employee; +import com.baeldung.reactive.webflux.EmployeeRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.springframework.web.reactive.function.BodyExtractors.toMono; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +@Configuration +public class EmployeeFunctionalConfig { + + @Bean + EmployeeRepository employeeRepository() { + return new EmployeeRepository(); + } + + @Bean + RouterFunction getAllEmployeesRoute() { + return route(GET("/employees"), + req -> ok().body( + employeeRepository().findAllEmployees(), Employee.class)); + } + + @Bean + RouterFunction getEmployeeByIdRoute() { + return route(GET("/employees/{id}"), + req -> ok().body( + employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)); + } + + @Bean + RouterFunction updateEmployeeRoute() { + return route(POST("/employees/update"), + req -> req.body(toMono(Employee.class)) + .doOnNext(employeeRepository()::updateEmployee) + .then(ok().build())); + } + + @Bean + RouterFunction composedRoutes() { + return + route(GET("/employees"), + req -> ok().body( + employeeRepository().findAllEmployees(), Employee.class)) + + .and(route(GET("/employees/{id}"), + req -> ok().body( + employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class))) + + .and(route(POST("/employees/update"), + req -> req.body(toMono(Employee.class)) + .doOnNext(employeeRepository()::updateEmployee) + .then(ok().build()))); + } + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.csrf() + .disable() + .authorizeExchange() + .anyExchange() + .permitAll(); + return http.build(); + } +} diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalApplication.java b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalApplication.java similarity index 60% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalApplication.java rename to spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalApplication.java index 1f2bd871fc..e90f5c0e96 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalApplication.java +++ b/spring-reactive/src/main/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalApplication.java @@ -1,13 +1,14 @@ -package com.baeldung.reactive.functional; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class EmployeeSpringFunctionalApplication { - - public static void main(String[] args) { - SpringApplication.run(EmployeeSpringFunctionalApplication.class, args); - } - -} +package com.baeldung.reactive.webflux.functional; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; + +@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class) +public class EmployeeSpringFunctionalApplication { + + public static void main(String[] args) { + SpringApplication.run(EmployeeSpringFunctionalApplication.class, args); + } + +} diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceIntegrationTest.java similarity index 54% rename from spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceIntegrationTest.java index 9d04541f8d..37e2ebe0ac 100644 --- a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.debugging.consumer; +package com.baeldung.reactive.debugging.consumer; import static org.assertj.core.api.Assertions.assertThat; @@ -8,13 +8,12 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.baeldung.reactive.debugging.consumer.model.Foo; +import com.baeldung.reactive.debugging.consumer.service.FooService; +import com.baeldung.reactive.debugging.consumer.utils.ListAppender; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.baeldung.debugging.consumer.model.Foo; -import com.baeldung.debugging.consumer.service.FooService; -import com.baeldung.debugging.consumer.utils.ListAppender; - import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import reactor.core.publisher.Flux; @@ -39,26 +38,26 @@ public class ConsumerFooServiceIntegrationTest { service.processFoo(flux); Collection allLoggedEntries = ListAppender.getEvents() - .stream() - .map(ILoggingEvent::getFormattedMessage) - .collect(Collectors.toList()); + .stream() + .map(ILoggingEvent::getFormattedMessage) + .collect(Collectors.toList()); Collection allSuppressedEntries = ListAppender.getEvents() - .stream() - .map(ILoggingEvent::getThrowableProxy) - .flatMap(t -> { - return Optional.ofNullable(t) - .map(IThrowableProxy::getSuppressed) - .map(Arrays::stream) - .orElse(Stream.empty()); - }) - .map(IThrowableProxy::getClassName) - .collect(Collectors.toList()); + .stream() + .map(ILoggingEvent::getThrowableProxy) + .flatMap(t -> { + return Optional.ofNullable(t) + .map(IThrowableProxy::getSuppressed) + .map(Arrays::stream) + .orElse(Stream.empty()); + }) + .map(IThrowableProxy::getClassName) + .collect(Collectors.toList()); assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("The following error happened on processFoo method!")) - .anyMatch(entry -> entry.contains("| onSubscribe")) - .anyMatch(entry -> entry.contains("| cancel()")); + .anyMatch(entry -> entry.contains("| onSubscribe")) + .anyMatch(entry -> entry.contains("| cancel()")); assertThat(allSuppressedEntries) - .anyMatch(entry -> entry.contains("reactor.core.publisher.FluxOnAssembly$OnAssemblyException")); + .anyMatch(entry -> entry.contains("reactor.core.publisher.FluxOnAssembly$OnAssemblyException")); } } diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceLiveTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceLiveTest.java similarity index 84% rename from spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceLiveTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceLiveTest.java index e61ea9e155..ff6e4b2bd2 100644 --- a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/ConsumerFooServiceLiveTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/ConsumerFooServiceLiveTest.java @@ -1,16 +1,15 @@ -package com.baeldung.debugging.consumer; +package com.baeldung.reactive.debugging.consumer; +import com.baeldung.reactive.debugging.consumer.service.FooService; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; -import com.baeldung.debugging.consumer.service.FooService; - /** * In order to run this live test, start the following classes: - * - com.baeldung.debugging.server.ServerDebuggingApplication - * - com.baeldung.debugging.consumer.ConsumerDebuggingApplication + * - com.baeldung.reactive.debugging.server.ServerDebuggingApplication + * - com.baeldung.reactive.debugging.consumer.ConsumerDebuggingApplication */ public class ConsumerFooServiceLiveTest { diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/utils/ListAppender.java b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/utils/ListAppender.java similarity index 90% rename from spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/utils/ListAppender.java rename to spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/utils/ListAppender.java index c8c1c110bb..fe8b04e824 100644 --- a/spring-5-reactive-2/src/test/java/com/baeldung/debugging/consumer/utils/ListAppender.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/debugging/consumer/utils/ListAppender.java @@ -1,11 +1,11 @@ -package com.baeldung.debugging.consumer.utils; - -import java.util.ArrayList; -import java.util.List; +package com.baeldung.reactive.debugging.consumer.utils; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.AppenderBase; +import java.util.ArrayList; +import java.util.List; + public class ListAppender extends AppenderBase { static private List events = new ArrayList<>(); diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java similarity index 100% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java index 38443a4eac..1167792542 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java @@ -1,9 +1,5 @@ package com.baeldung.reactive.errorhandling; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +12,10 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @DirtiesContext diff --git a/reactor-core/src/test/java/com/baeldung/reactor/introduction/ReactorIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/introduction/ReactorIntegrationTest.java similarity index 90% rename from reactor-core/src/test/java/com/baeldung/reactor/introduction/ReactorIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/introduction/ReactorIntegrationTest.java index a1acffac91..307cc2cfeb 100644 --- a/reactor-core/src/test/java/com/baeldung/reactor/introduction/ReactorIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/introduction/ReactorIntegrationTest.java @@ -1,8 +1,10 @@ -package com.baeldung.reactor.introduction; +package com.baeldung.reactive.introduction; import org.junit.Test; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import reactor.core.publisher.ConnectableFlux; import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; @@ -14,6 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class ReactorIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ReactorIntegrationTest.class); + @Test public void givenFlux_whenSubscribing_thenStream() { @@ -22,7 +26,7 @@ public class ReactorIntegrationTest { Flux.just(1, 2, 3, 4) .log() .map(i -> { - System.out.println(i + ":" + Thread.currentThread()); + LOGGER.debug("{}:{}", i, Thread.currentThread()); return i * 2; }) .subscribe(elements::add); @@ -97,7 +101,8 @@ public class ReactorIntegrationTest { Thread.sleep(1000); - assertThat(threadNames).containsExactly("parallel-1", "parallel-1", "parallel-1", "parallel-1"); + assertThat(threadNames).isNotEmpty(); + assertThat(threadNames).hasSize(4); } @Test diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/security/SecurityIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/security/SecurityIntegrationTest.java similarity index 75% rename from spring-5-reactive-security/src/test/java/com/baeldung/security/SecurityIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/security/SecurityIntegrationTest.java index 423500e09c..06644fbf77 100644 --- a/spring-5-reactive-security/src/test/java/com/baeldung/security/SecurityIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/security/SecurityIntegrationTest.java @@ -1,19 +1,16 @@ -package com.baeldung.security; +package com.baeldung.reactive.security; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import com.baeldung.reactive.security.SpringSecurity5Application; - -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) @ContextConfiguration(classes = SpringSecurity5Application.class) public class SecurityIntegrationTest { @@ -22,7 +19,7 @@ public class SecurityIntegrationTest { private WebTestClient rest; - @Before + @BeforeEach public void setup() { this.rest = WebTestClient.bindToApplicationContext(this.context).configureClient().build(); } @@ -33,7 +30,6 @@ public class SecurityIntegrationTest { } @Test - @Ignore @WithMockUser public void whenHasCredentials_thenSeesGreeting() { this.rest.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello, user"); diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/SpringContextTest.java similarity index 73% rename from spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webclient/SpringContextTest.java index 8d2ca41451..4a1fc4390a 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/SpringContextTest.java @@ -1,10 +1,8 @@ -package com.baeldung.web.client; +package com.baeldung.reactive.webclient; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import com.baeldung.web.reactive.client.WebClientApplication; - @SpringBootTest(classes = WebClientApplication.class) public class SpringContextTest { diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebClientIntegrationTest.java similarity index 98% rename from spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebClientIntegrationTest.java index 7e1fc86847..28b4c19a10 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebClientIntegrationTest.java @@ -1,15 +1,9 @@ -package com.baeldung.web.client; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.TimeUnit; +package com.baeldung.reactive.webclient; +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -34,18 +28,20 @@ import org.springframework.web.reactive.function.client.WebClient.RequestHeaders import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec; import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; import org.springframework.web.reactive.function.client.WebClientRequestException; - -import com.baeldung.web.reactive.client.Foo; -import com.baeldung.web.reactive.client.WebClientApplication; - -import io.netty.channel.ChannelOption; -import io.netty.handler.timeout.ReadTimeoutException; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; import reactor.core.publisher.Mono; import reactor.netty.http.client.HttpClient; import reactor.test.StepVerifier; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; + @SpringBootTest(classes = WebClientApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) public class WebClientIntegrationTest { @@ -211,8 +207,7 @@ public class WebClientIntegrationTest { ResponseSpec responseSpecPostString = createDefaultPostResourceRequestResponse().retrieve(); Mono responsePostString = responseSpecPostString.bodyToMono(String.class); Mono responsePostString2 = createDefaultPostResourceRequestResponse().exchangeToMono(response -> { - if (response.statusCode() - .equals(HttpStatus.OK)) { + if (response.statusCode() == HttpStatus.OK) { return response.bodyToMono(String.class); } else if (response.statusCode() .is4xxClientError()) { @@ -223,8 +218,7 @@ public class WebClientIntegrationTest { } }); Mono responsePostNoBody = createDefaultPostResourceRequest().exchangeToMono(response -> { - if (response.statusCode() - .equals(HttpStatus.OK)) { + if (response.statusCode() == HttpStatus.OK) { return response.bodyToMono(String.class); } else if (response.statusCode() .is4xxClientError()) { diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebControllerIntegrationTest.java similarity index 89% rename from spring-5-reactive-2/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebControllerIntegrationTest.java index 09c3a5fb84..3ab687bb41 100644 --- a/spring-5-reactive-2/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.webclient; +package com.baeldung.reactive.webclient; import org.junit.Before; import org.junit.Test; @@ -6,9 +6,11 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WebClientApplication.class) public class WebControllerIntegrationTest { diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebTestClientIntegrationTest.java similarity index 94% rename from spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebTestClientIntegrationTest.java index 07a4c81c91..90f4a0eca2 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webclient/WebTestClientIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.client; +package com.baeldung.reactive.webclient; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -12,10 +12,6 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.WebHandler; - -import com.baeldung.web.reactive.client.WebClientApplication; -import com.baeldung.web.reactive.client.WebClientController; - import reactor.core.publisher.Mono; @SpringBootTest(classes = WebClientApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webclientrequests/WebClientRequestsUnitTest.java similarity index 99% rename from spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webclientrequests/WebClientRequestsUnitTest.java index 353cb24d0a..ff59f12391 100644 --- a/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webclientrequests/WebClientRequestsUnitTest.java @@ -1,10 +1,5 @@ -package com.baeldung.spring.webclientrequests; +package com.baeldung.reactive.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; @@ -22,6 +17,12 @@ import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.DefaultUriBuilderFactory; import reactor.core.publisher.Mono; +import java.time.Duration; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + @RunWith(SpringRunner.class) @WebFluxTest public class WebClientRequestsUnitTest { @@ -48,7 +49,6 @@ public class WebClientRequestsUnitTest { .build(); } - @Test public void whenCallSimpleURI_thenURIMatched() { this.webClient.get() diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webflux/annotation/EmployeeControllerIntegrationTest.java similarity index 88% rename from spring-5-reactive-security/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webflux/annotation/EmployeeControllerIntegrationTest.java index 12a21ed4ef..24c4303e83 100644 --- a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webflux/annotation/EmployeeControllerIntegrationTest.java @@ -1,10 +1,8 @@ -package com.baeldung.reactive.webflux; - -import static org.mockito.BDDMockito.given; - -import java.util.ArrayList; -import java.util.List; +package com.baeldung.reactive.webflux.annotation; +import com.baeldung.reactive.webflux.Employee; +import com.baeldung.reactive.webflux.EmployeeRepository; +import com.baeldung.reactive.webflux.annotation.EmployeeSpringApplication; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; @@ -14,16 +12,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; - -import com.baeldung.webflux.EmployeeSpringApplication; -import com.baeldung.webflux.Employee; -import com.baeldung.webflux.EmployeeRepository; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.BDDMockito.given; + @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes=EmployeeSpringApplication.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes= EmployeeSpringApplication.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class EmployeeControllerIntegrationTest { diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalIntegrationTest.java b/spring-reactive/src/test/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalIntegrationTest.java similarity index 94% rename from spring-5-reactive-security/src/test/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalIntegrationTest.java rename to spring-reactive/src/test/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalIntegrationTest.java index d8e2f0b23b..da866724cc 100644 --- a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/functional/EmployeeSpringFunctionalIntegrationTest.java +++ b/spring-reactive/src/test/java/com/baeldung/reactive/webflux/functional/EmployeeSpringFunctionalIntegrationTest.java @@ -1,7 +1,7 @@ -package com.baeldung.reactive.functional; +package com.baeldung.reactive.webflux.functional; -import com.baeldung.webflux.Employee; -import com.baeldung.webflux.EmployeeRepository; +import com.baeldung.reactive.webflux.Employee; +import com.baeldung.reactive.webflux.EmployeeRepository; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-reactive/src/test/resources/logback-test.xml b/spring-reactive/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..69c10177a9 --- /dev/null +++ b/spring-reactive/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-roo/pom.xml b/spring-roo/pom.xml index d900e131d4..b55a334256 100644 --- a/spring-roo/pom.xml +++ b/spring-roo/pom.xml @@ -599,7 +599,7 @@ 3.0.0.RELEASE 2.0.0 2.0.1 - 5.0.11 + 5.3.2 1.0 3.3.6 1.10.12 diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/SpringSchedulingConfig.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/SpringSchedulingConfig.java index 5d7f1cf88f..4bdfad3267 100644 --- a/spring-scheduling/src/main/java/com/baeldung/scheduling/SpringSchedulingConfig.java +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/SpringSchedulingConfig.java @@ -5,7 +5,9 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; @Configuration @EnableScheduling @@ -13,6 +15,14 @@ import org.springframework.scheduling.annotation.EnableScheduling; @PropertySource("classpath:springScheduled.properties") public class SpringSchedulingConfig { + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); + threadPoolTaskScheduler.setPoolSize(5); + threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler"); + return threadPoolTaskScheduler; + } + @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); diff --git a/spring-security-modules/spring-5-security-oauth/pom.xml b/spring-security-modules/spring-5-security-oauth/pom.xml index 194ace35b0..aa4958ae47 100644 --- a/spring-security-modules/spring-5-security-oauth/pom.xml +++ b/spring-security-modules/spring-5-security-oauth/pom.xml @@ -68,7 +68,8 @@ - + 2.5.2 com.baeldung.oauth2.SpringOAuthApplication diff --git a/spring-security-modules/spring-5-security/src/test/resources/logback-test.xml b/spring-security-modules/spring-5-security/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-security-modules/spring-ldap/pom.xml b/spring-security-modules/spring-ldap/pom.xml index 44f754673f..086be2df5a 100644 --- a/spring-security-modules/spring-ldap/pom.xml +++ b/spring-security-modules/spring-ldap/pom.xml @@ -106,7 +106,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} integration-test diff --git a/spring-security-modules/spring-security-core/README.md b/spring-security-modules/spring-security-core/README.md index f9c6d2e5fb..9f8e4dda53 100644 --- a/spring-security-modules/spring-security-core/README.md +++ b/spring-security-modules/spring-security-core/README.md @@ -10,7 +10,6 @@ This module contains articles about core Spring Security - [Deny Access on Missing @PreAuthorize to Spring Controller Methods](https://www.baeldung.com/spring-deny-access) - [Spring Security: Check If a User Has a Role in Java](https://www.baeldung.com/spring-security-check-user-role) - [Filtering Jackson JSON Output Based on Spring Security Role](https://www.baeldung.com/spring-security-role-filter-json) -- [Spring @EnableWebSecurity vs. @EnableGlobalMethodSecurity](https://www.baeldung.com/spring-enablewebsecurity-vs-enableglobalmethodsecurity) ### Build the Project diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/PasswordEncoderConfig.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/PasswordEncoderConfig.java new file mode 100644 index 0000000000..5df32d6392 --- /dev/null +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/PasswordEncoderConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.app.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java index 15af160135..c0abd3cec1 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java @@ -22,15 +22,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { } @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + public void configureGlobal(AuthenticationManagerBuilder auth, PasswordEncoder passwordEncoder) throws Exception { auth.inMemoryAuthentication() - .withUser("jim").password(passwordEncoder().encode("jim")).roles("USER", "ACTUATOR") - .and().withUser("pam").password(passwordEncoder().encode("pam")).roles("USER") - .and().withUser("michael").password(passwordEncoder().encode("michael")).roles("MANAGER"); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); + .withUser("jim").password(passwordEncoder.encode("jim")).roles("USER", "ACTUATOR") + .and().withUser("pam").password(passwordEncoder.encode("pam")).roles("USER") + .and().withUser("michael").password(passwordEncoder.encode("michael")).roles("MANAGER"); } + } diff --git a/spring-security-modules/spring-security-oidc/src/test/resources/logback-test.xml b/spring-security-modules/spring-security-oidc/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-1/pom.xml b/spring-security-modules/spring-security-web-boot-1/pom.xml index a376a49b4c..3f6001686d 100644 --- a/spring-security-modules/spring-security-web-boot-1/pom.xml +++ b/spring-security-modules/spring-security-web-boot-1/pom.xml @@ -59,11 +59,6 @@ postgresql runtime - - org.hamcrest - hamcrest - test - org.springframework spring-test diff --git a/spring-security-modules/spring-security-web-boot-2/pom.xml b/spring-security-modules/spring-security-web-boot-2/pom.xml index ade644741d..91b6ff8724 100644 --- a/spring-security-modules/spring-security-web-boot-2/pom.xml +++ b/spring-security-modules/spring-security-web-boot-2/pom.xml @@ -59,11 +59,6 @@ postgresql runtime - - org.hamcrest - hamcrest - test - org.springframework spring-test diff --git a/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/PasswordEncoderConfig.java b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/PasswordEncoderConfig.java new file mode 100644 index 0000000000..4c21b315fb --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/PasswordEncoderConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.jdbcauthentication.h2.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/SecurityConfiguration.java b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/SecurityConfiguration.java index 50dc5b6958..49804e8458 100644 --- a/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/SecurityConfiguration.java +++ b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/jdbcauthentication/h2/config/SecurityConfiguration.java @@ -1,19 +1,18 @@ package com.baeldung.jdbcauthentication.h2.config; -import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import javax.sql.DataSource; + @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeRequests() @@ -32,20 +31,15 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { } @Autowired - private DataSource dataSource; - - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + public void configureGlobal(AuthenticationManagerBuilder auth, + DataSource dataSource, + PasswordEncoder passwordEncoder) throws Exception { auth.jdbcAuthentication() - .dataSource(dataSource) - .withDefaultSchema() - .withUser(User.withUsername("user") - .password(passwordEncoder().encode("pass")) - .roles("USER")); + .dataSource(dataSource) + .withDefaultSchema() + .withUser(User.withUsername("user") + .password(passwordEncoder.encode("pass")) + .roles("USER")); } - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/README.md b/spring-security-modules/spring-security-web-boot-3/README.md index e95071b825..45fede7a4c 100644 --- a/spring-security-modules/spring-security-web-boot-3/README.md +++ b/spring-security-modules/spring-security-web-boot-3/README.md @@ -11,4 +11,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [Spring Security – Request Rejected Exception](https://www.baeldung.com/spring-security-request-rejected-exception) - [Spring Security – Cache Control Headers](https://www.baeldung.com/spring-security-cache-control-headers) - [Fixing 401s with CORS Preflights and Spring Security](https://www.baeldung.com/spring-security-cors-preflight) +- [Content Security Policy with Spring Security](https://www.baeldung.com/spring-security-csp) - More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-2) diff --git a/spring-security-modules/spring-security-web-boot-3/pom.xml b/spring-security-modules/spring-security-web-boot-3/pom.xml index 9d09d60611..5f2a455294 100644 --- a/spring-security-modules/spring-security-web-boot-3/pom.xml +++ b/spring-security-modules/spring-security-web-boot-3/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 spring-security-web-boot-3 0.0.1-SNAPSHOT @@ -25,6 +23,25 @@ org.springframework.boot spring-boot-starter-web + + commons-io + commons-io + ${commons-io.version} + + + org.webjars + webjars-locator-core + + + org.webjars + bootstrap + ${bootstrap.version} + + + org.webjars + jquery + ${jquery.version} + org.springframework.boot spring-boot-starter-test @@ -41,4 +58,10 @@ + + 5.1.1 + 3.6.0 + + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyApplication.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyApplication.java new file mode 100644 index 0000000000..d009f64918 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.contentsecuritypolicy; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ContentSecurityPolicyApplication { + public static void main(String[] args) { + SpringApplication.run(ContentSecurityPolicyApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyController.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyController.java new file mode 100644 index 0000000000..f57833fd7b --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyController.java @@ -0,0 +1,23 @@ +package com.baeldung.contentsecuritypolicy; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +@RestController +public class ContentSecurityPolicyController { + private static final Logger logger = LoggerFactory.getLogger(ContentSecurityPolicyController.class); + + @PostMapping("/report") + public void report(HttpServletRequest request) throws IOException { + if (logger.isInfoEnabled()) { + logger.info("Report: {}", IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8)); + } + } +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicySecurityConfiguration.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicySecurityConfiguration.java new file mode 100644 index 0000000000..1593af9c66 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicySecurityConfiguration.java @@ -0,0 +1,26 @@ +package com.baeldung.contentsecuritypolicy; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.header.writers.StaticHeadersWriter; + +@Configuration +public class ContentSecurityPolicySecurityConfiguration extends WebSecurityConfigurerAdapter { + private static final String REPORT_TO = "{\"group\":\"csp-violation-report\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://localhost:8080/report\"}]}"; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf() + .disable() + .authorizeRequests() + .antMatchers("/**") + .permitAll() + .and() + .headers() + .addHeaderWriter(new StaticHeadersWriter("Report-To", REPORT_TO)) + .xssProtection() + .and() + .contentSecurityPolicy("form-action 'self'; report-uri /report; report-to csp-violation-report"); + } +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/index.html b/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/index.html new file mode 100644 index 0000000000..52ecb198df --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/index.html @@ -0,0 +1,67 @@ + + + + Content Security Policy + + + + + + + + + + +
+
+ +
+
+ +
+
+
+
+
+
+

Login

+
+
+
+ + +
+
+
+ + +
+ +
+ +
+
+
+ +
+
+ +
+ + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/main.css b/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/main.css new file mode 100644 index 0000000000..dac839bc64 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/resources/static/main.css @@ -0,0 +1,26 @@ +html, body{ + font-family: Raleway, serif; + background-color: #f5f5f5; +} +.navbar +{ + background-color: #63b175 !important; +} +.navbar-brand +{ + font-size: 1.75rem; + font-weight: bold; +} +/* +hr{ + border: 0px dotted rgba(249, 249, 249, 0.88); +}*/ + +hr { + border: 0; + border-bottom: 1px dashed #969595; + background: #969595; +} +label{ + font-weight: bold; +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/src/test/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyUnitTest.java b/spring-security-modules/spring-security-web-boot-3/src/test/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyUnitTest.java new file mode 100644 index 0000000000..0e06a7ef35 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/test/java/com/baeldung/contentsecuritypolicy/ContentSecurityPolicyUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.contentsecuritypolicy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + +import org.springframework.http.HttpStatus; + +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import javax.servlet.http.HttpServletResponse; + +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + +@WebMvcTest +@AutoConfigureMockMvc +@DisplayName("Content Security Policy Unit Tests") +class ContentSecurityPolicyUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + @DisplayName("Test to Check Bad URL") + void whenWrongUri_thenThrow404() throws Exception { + MvcResult result = mockMvc.perform(post("/reports").content("").contentType(MediaType.APPLICATION_JSON)).andReturn(); + + assertEquals(HttpStatus.NOT_FOUND.value(), result.getResponse().getStatus()); + } + + @Test + @DisplayName("Test to Check Page rendering") + void whenGet_thenRenderPage() throws Exception { + MvcResult result = mockMvc.perform(get("/").content("")).andReturn(); + + assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus()); + assertEquals("text/html", MediaType.TEXT_HTML_VALUE); + } + + @Test + @DisplayName("Test to Check CSP headers") + void whenGet_thenCheckCspHeaders() throws Exception { + MvcResult result = mockMvc.perform(get("/").content("")).andReturn(); + HttpServletResponse response = result.getResponse(); + Collection headers = response.getHeaderNames(); + + assertNotNull(result); + assertNotNull(headers); + assertEquals(HttpStatus.OK.value(), response.getStatus()); + assertEquals("text/html", MediaType.TEXT_HTML_VALUE); + assertTrue(headers.contains("Report-To")); + assertTrue(headers.contains("Content-Security-Policy")); + } +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/test/resources/logback-test.xml b/spring-security-modules/spring-security-web-boot-3/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-digest-auth/pom.xml b/spring-security-modules/spring-security-web-digest-auth/pom.xml index 710a3dd3b6..4a20f007d5 100644 --- a/spring-security-modules/spring-security-web-digest-auth/pom.xml +++ b/spring-security-modules/spring-security-web-digest-auth/pom.xml @@ -174,7 +174,6 @@ 4.2.6.RELEASE - 19.0 4.4.5 4.5.2 diff --git a/spring-security-modules/spring-security-web-login/README.md b/spring-security-modules/spring-security-web-login/README.md index 9521a430c2..8b9c1583f6 100644 --- a/spring-security-modules/spring-security-web-login/README.md +++ b/spring-security-modules/spring-security-web-login/README.md @@ -1,6 +1,6 @@ ## Spring Security Login -This module contains articles about login mechanisms with Spring Security +This module contains articles about login mechanisms with Spring Security. ### The Course The "Learn Spring Security" Classes: http://github.learnspringsecurity.com @@ -17,3 +17,12 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ``` mvn clean install ``` + +### Run the Project + +- Run the application using Maven Cargo plugin. +``` +mvn cargo:run +``` +- Go to the login page at http://localhost:8082/spring-security-web-login/login.html +- Login using ```user1/user1Pass``` details. \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-login/pom.xml b/spring-security-modules/spring-security-web-login/pom.xml index ac5393c1a0..3d9947c519 100644 --- a/spring-security-modules/spring-security-web-login/pom.xml +++ b/spring-security-modules/spring-security-web-login/pom.xml @@ -137,17 +137,9 @@ org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} + cargo-maven3-plugin + ${cargo-maven3-plugin.version} - true - - jetty8x - embedded - - - - 8082 @@ -160,7 +152,7 @@ - 1.6.1 + 1.9.9 \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/AppInitializer.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/AppInitializer.java index 4f38d190eb..cbdf8dc684 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/AppInitializer.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/AppInitializer.java @@ -1,9 +1,5 @@ package com.baeldung; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; - import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -11,10 +7,13 @@ import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.DispatcherServlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; + public class AppInitializer implements WebApplicationInitializer { @Override - public void onStartup(final ServletContext sc) throws ServletException { + public void onStartup(final ServletContext sc) { AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); @@ -24,7 +23,7 @@ public class AppInitializer implements WebApplicationInitializer { ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); appServlet.setLoadOnStartup(1); appServlet.addMapping("/"); - + sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain")) .addMappingForUrlPatterns(null, false, "/*"); diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAccessDeniedHandler.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAccessDeniedHandler.java index 9d9fa81dc0..39355202e3 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAccessDeniedHandler.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAccessDeniedHandler.java @@ -1,25 +1,22 @@ package com.baeldung.security; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.AccessDeniedHandler; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + public class CustomAccessDeniedHandler implements AccessDeniedHandler { public static final Logger LOG = LoggerFactory.getLogger(CustomAccessDeniedHandler.class); @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException, ServletException { + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException { Authentication auth = SecurityContextHolder.getContext() .getAuthentication(); if (auth != null) { diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAuthenticationFailureHandler.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAuthenticationFailureHandler.java index 410d3f1ce9..ce3f299dac 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAuthenticationFailureHandler.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomAuthenticationFailureHandler.java @@ -13,7 +13,7 @@ import java.util.Calendar; public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override - public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { + public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException { httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); String jsonPayload = "{\"message\" : \"%s\", \"timestamp\" : \"%s\" }"; diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomLogoutSuccessHandler.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomLogoutSuccessHandler.java index 7949eee69a..ee3bd62958 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomLogoutSuccessHandler.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/CustomLogoutSuccessHandler.java @@ -12,12 +12,6 @@ import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuc public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler { - public CustomLogoutSuccessHandler() { - super(); - } - - // API - @Override public void onLogoutSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException, ServletException { final String refererUrl = request.getHeader("Referer"); diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/config/SecSecurityConfig.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/config/SecSecurityConfig.java index 15fa06aa3e..cfdaf7a13e 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/config/SecSecurityConfig.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/security/config/SecSecurityConfig.java @@ -23,10 +23,6 @@ import com.baeldung.security.CustomLogoutSuccessHandler; @Profile("!https") public class SecSecurityConfig extends WebSecurityConfigurerAdapter { - public SecSecurityConfig() { - super(); - } - @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -81,7 +77,7 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { public AuthenticationFailureHandler authenticationFailureHandler() { return new CustomAuthenticationFailureHandler(); } - + @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/ChannelSecSecurityConfig.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/ChannelSecSecurityConfig.java index e9a6a9e120..151df18d11 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/ChannelSecSecurityConfig.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/ChannelSecSecurityConfig.java @@ -17,10 +17,6 @@ import com.baeldung.security.CustomLogoutSuccessHandler; @Profile("https") public class ChannelSecSecurityConfig extends WebSecurityConfigurerAdapter { - public ChannelSecSecurityConfig() { - super(); - } - @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { // @formatter:off diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/MvcConfig.java index 082477c98c..7b27d637be 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/MvcConfig.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/MvcConfig.java @@ -13,12 +13,6 @@ import org.springframework.web.servlet.view.JstlView; @Configuration public class MvcConfig implements WebMvcConfigurer { - public MvcConfig() { - super(); - } - - // API - @Override public void addViewControllers(final ViewControllerRegistry registry) { diff --git a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/RedirectionSecurityConfig.java b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/RedirectionSecurityConfig.java index 3516438a6e..b27d999d56 100644 --- a/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/RedirectionSecurityConfig.java +++ b/spring-security-modules/spring-security-web-login/src/main/java/com/baeldung/spring/RedirectionSecurityConfig.java @@ -11,10 +11,6 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti //@Profile("!https") public class RedirectionSecurityConfig extends WebSecurityConfigurerAdapter { - public RedirectionSecurityConfig() { - super(); - } - @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() diff --git a/spring-security-modules/spring-security-web-mvc-custom/pom.xml b/spring-security-modules/spring-security-web-mvc-custom/pom.xml index 533a1bf83d..104b7025ad 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/pom.xml +++ b/spring-security-modules/spring-security-web-mvc-custom/pom.xml @@ -97,12 +97,6 @@ ${jstl.version} runtime - - - - - - com.fasterxml.jackson.core @@ -172,8 +166,6 @@ - - 19.0 3.2.2 1.6.1 diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfCookieEnabledIntegrationTest.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfCookieEnabledIntegrationTest.java new file mode 100644 index 0000000000..73f83f9b0c --- /dev/null +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfCookieEnabledIntegrationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.security.csrf; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.baeldung.security.spring.SecurityWithCsrfCookieConfig; +import com.baeldung.spring.MvcConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithCsrfCookieConfig.class, MvcConfig.class }) +public class CsrfCookieEnabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo()) + .with(testUser())) + .andExpect(status().isForbidden()); + // @formatter:on + } + + @Test + public void givenCsrf_whenAddFoo_thenCreated() throws Exception { + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo()) + .with(testUser()) + .with(csrf())) + .andExpect(status().isCreated()); + // @formatter:on + } + +} diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfDisabledIntegrationTest.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfDisabledIntegrationTest.java index a1c8be9daf..6dc01ab2bd 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfDisabledIntegrationTest.java +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfDisabledIntegrationTest.java @@ -14,12 +14,25 @@ public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { @Test public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo())) + .andExpect(status().isUnauthorized()); + // @formatter:on } @Test public void givenAuth_whenAddFoo_thenCreated() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo()) + .with(testUser())) + .andExpect(status().isCreated()); + // @formatter:on } } diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfEnabledIntegrationTest.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfEnabledIntegrationTest.java index 87e5005e17..50af9bba6f 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfEnabledIntegrationTest.java +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/csrf/CsrfEnabledIntegrationTest.java @@ -15,12 +15,27 @@ public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { @Test public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden()); + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo()) + .with(testUser())) + .andExpect(status().isForbidden()); + // @formatter:on } @Test public void givenCsrf_whenAddFoo_thenCreated() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated()); + // @formatter:off + mvc + .perform(post("/auth/foos") + .contentType(MediaType.APPLICATION_JSON) + .content(createFoo()) + .with(testUser()) + .with(csrf())) + .andExpect(status().isCreated()); + // @formatter:on } } diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfConfig.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfConfig.java index 9b3ac50546..4ec7a50abc 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfConfig.java +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfConfig.java @@ -27,7 +27,17 @@ public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN"); + // @formatter:off + auth + .inMemoryAuthentication() + .withUser("user1") + .password("user1Pass") + .authorities("ROLE_USER") + .and() + .withUser("admin") + .password("adminPass") + .authorities("ROLE_ADMIN"); + // @formatter:on } @Override @@ -45,8 +55,7 @@ public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { .and() .httpBasic() .and() - .headers().cacheControl().disable() - ; + .headers().cacheControl().disable(); // @formatter:on } diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfCookieConfig.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfCookieConfig.java new file mode 100644 index 0000000000..5b58349629 --- /dev/null +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithCsrfCookieConfig.java @@ -0,0 +1,67 @@ +package com.baeldung.security.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityWithCsrfCookieConfig extends WebSecurityConfigurerAdapter { + + public SecurityWithCsrfCookieConfig() { + super(); + } + + @Bean("authenticationManager") + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth + .inMemoryAuthentication() + .withUser("user1") + .password("user1Pass") + .authorities("ROLE_USER") + .and() + .withUser("admin") + .password("adminPass") + .authorities("ROLE_ADMIN"); + // @formatter:on + } + + @Override + public void configure(final WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .antMatchers("/auth/admin/*").hasAnyRole("ROLE_ADMIN") + .anyRequest().authenticated() + .and() + .httpBasic() + .and() + .headers().cacheControl().disable() + // Stateless API CSRF configuration + .and() + .csrf() + .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); + // @formatter:on + } + +} diff --git a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithoutCsrfConfig.java b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithoutCsrfConfig.java index 4a1263b498..bd9ca67ad5 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithoutCsrfConfig.java +++ b/spring-security-modules/spring-security-web-mvc-custom/src/test/java/com/baeldung/security/spring/SecurityWithoutCsrfConfig.java @@ -27,7 +27,17 @@ public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN"); + // @formatter:off + auth + .inMemoryAuthentication() + .withUser("user1") + .password("user1Pass") + .authorities("ROLE_USER") + .and() + .withUser("admin") + .password("adminPass") + .authorities("ROLE_ADMIN"); + // @formatter:on } @Override @@ -47,8 +57,7 @@ public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { .and() .headers().cacheControl().disable() .and() - .csrf().disable() - ; + .csrf().disable(); // @formatter:on } diff --git a/spring-security-modules/spring-security-web-persistent-login/pom.xml b/spring-security-modules/spring-security-web-persistent-login/pom.xml index 2d931c416c..beafc10ffd 100644 --- a/spring-security-modules/spring-security-web-persistent-login/pom.xml +++ b/spring-security-modules/spring-security-web-persistent-login/pom.xml @@ -127,12 +127,6 @@ ${spring-boot.version} test - - - - - - @@ -177,8 +171,6 @@ 4.2.6.RELEASE 9.4.1212 - - 19.0 1.6.1 1.5.10.RELEASE diff --git a/spring-security-modules/spring-security-web-react/pom.xml b/spring-security-modules/spring-security-web-react/pom.xml index a31fafc5ad..6c66206c55 100644 --- a/spring-security-modules/spring-security-web-react/pom.xml +++ b/spring-security-modules/spring-security-web-react/pom.xml @@ -141,8 +141,6 @@ --> - - 19.0 2.7 1.12.0 diff --git a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/MvcConfig.java index f8acdfe2ac..226459db75 100644 --- a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/MvcConfig.java +++ b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/MvcConfig.java @@ -1,18 +1,20 @@ package com.baeldung.spring; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @EnableWebMvc @Configuration -public class MvcConfig extends WebMvcConfigurerAdapter { +@ComponentScan(basePackages = { "com.baeldung.spring" }) +public class MvcConfig implements WebMvcConfigurer { public MvcConfig() { super(); @@ -22,8 +24,6 @@ public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/anonymous.html"); registry.addViewController("/login.html"); @@ -35,7 +35,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/view/react/build/static/"); - + registry.addResourceHandler("/*.js").addResourceLocations("/WEB-INF/view/react/build/"); registry.addResourceHandler("/*.json").addResourceLocations("/WEB-INF/view/react/build/"); registry.addResourceHandler("/*.ico").addResourceLocations("/WEB-INF/view/react/build/"); diff --git a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java new file mode 100644 index 0000000000..4084df9698 --- /dev/null +++ b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java @@ -0,0 +1,31 @@ +package com.baeldung.spring; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/rest") +public class RestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(RestController.class); + + @GetMapping + public ResponseEntity get(HttpServletRequest request) { + CsrfToken token = (CsrfToken) request.getAttribute("_csrf"); + LOGGER.info("{}={}", token.getHeaderName(), token.getToken()); + return ResponseEntity.ok().build(); + } + + @PostMapping + public ResponseEntity post(HttpServletRequest request) { + // Same impl as GET for testing purpose + return this.get(request); + } +} diff --git a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java index 7b67028647..d560589cce 100644 --- a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java @@ -7,6 +7,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; @Configuration @EnableWebSecurity @@ -21,11 +22,11 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(final AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth.inMemoryAuthentication() - .withUser("user1").password("user1Pass").roles("USER") + .withUser("user1").password("{noop}user1Pass").roles("USER") .and() - .withUser("user2").password("user2Pass").roles("USER") + .withUser("user2").password("{noop}user2Pass").roles("USER") .and() - .withUser("admin").password("admin0Pass").roles("ADMIN"); + .withUser("admin").password("{noop}admin0Pass").roles("ADMIN"); // @formatter:on } @@ -33,11 +34,11 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(final HttpSecurity http) throws Exception { // @formatter:off http - .csrf().disable() + .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/anonymous*").anonymous() - .antMatchers(HttpMethod.GET, "/index*", "/static/**", "/*.js", "/*.json", "/*.ico").permitAll() + .antMatchers(HttpMethod.GET, "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/rest").permitAll() .anyRequest().authenticated() .and() .formLogin() diff --git a/spring-security-modules/spring-security-web-react/src/main/resources/logback.xml b/spring-security-modules/spring-security-web-react/src/main/resources/logback.xml index 25f3f36d1a..2cc702de59 100644 --- a/spring-security-modules/spring-security-web-react/src/main/resources/logback.xml +++ b/spring-security-modules/spring-security-web-react/src/main/resources/logback.xml @@ -12,7 +12,7 @@ - + diff --git a/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/homepage.jsp index c9d88cbc9b..d64f80a5cb 100644 --- a/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/homepage.jsp +++ b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/homepage.jsp @@ -1,11 +1,30 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> - + + +

This is the body of the sample view

+
+

CSRF Testing

+
+ CSRF Token: + + +
+
+
+   + +
+
+
Request Result:

+
+ +

Roles

This text is only visible to a user

@@ -22,5 +41,26 @@ ">Logout + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/csrf.js b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/csrf.js new file mode 100644 index 0000000000..657cc31f41 --- /dev/null +++ b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/csrf.js @@ -0,0 +1,3 @@ +window.getCsrfToken = () => { + return document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$)|^.*$/, '$1'); +} diff --git a/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/index.html b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/index.html index 0c3f78d7b3..6d4894da42 100644 --- a/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/index.html +++ b/spring-security-modules/spring-security-web-react/src/main/webapp/WEB-INF/view/react/public/index.html @@ -6,6 +6,7 @@ + - - - - - - - - - - - org.apache.httpcomponents httpcore @@ -246,8 +235,6 @@ 4.4.11 4.5.8 - - 19.0 1.6.1
diff --git a/spring-security-modules/spring-security-web-rest-custom/pom.xml b/spring-security-modules/spring-security-web-rest-custom/pom.xml index 85e50412ad..d420c45df2 100644 --- a/spring-security-modules/spring-security-web-rest-custom/pom.xml +++ b/spring-security-modules/spring-security-web-rest-custom/pom.xml @@ -115,17 +115,6 @@ commons-lang3 ${commons-lang3.version} - - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - @@ -175,8 +164,6 @@ - - 19.0 1.2 1.6.1 diff --git a/spring-security-modules/spring-security-web-rest/pom.xml b/spring-security-modules/spring-security-web-rest/pom.xml index 2fc50b2674..99a040293b 100644 --- a/spring-security-modules/spring-security-web-rest/pom.xml +++ b/spring-security-modules/spring-security-web-rest/pom.xml @@ -244,8 +244,6 @@ 1.1.0.Final - - 26.0-jre 2.9.0 diff --git a/spring-security-modules/spring-security-web-thymeleaf/pom.xml b/spring-security-modules/spring-security-web-thymeleaf/pom.xml index 8e6e0856af..c13aa6a471 100644 --- a/spring-security-modules/spring-security-web-thymeleaf/pom.xml +++ b/spring-security-modules/spring-security-web-thymeleaf/pom.xml @@ -29,7 +29,6 @@ org.springframework.boot spring-boot-starter-web - org.springframework.boot spring-boot-starter-test @@ -46,13 +45,4 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/PasswordEncoderConfiguration.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/PasswordEncoderConfiguration.java new file mode 100644 index 0000000000..5ffe2c35f9 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/PasswordEncoderConfiguration.java @@ -0,0 +1,15 @@ +package com.baeldung.springsecuritythymeleaf; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfiguration { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/SecurityConfiguration.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/SecurityConfiguration.java index f7f8cfb708..8e9047f629 100644 --- a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/SecurityConfiguration.java +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/springsecuritythymeleaf/SecurityConfiguration.java @@ -8,6 +8,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @@ -32,19 +33,15 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { } @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + public void configureGlobal(AuthenticationManagerBuilder auth, PasswordEncoder passwordEncoder) throws Exception { auth.inMemoryAuthentication() .withUser("user") - .password(passwordEncoder().encode("password")) + .password(passwordEncoder.encode("password")) .roles("USER") .and() .withUser("admin") - .password(passwordEncoder().encode("admin")) + .password(passwordEncoder.encode("admin")) .roles("ADMIN"); } - - @Bean - public BCryptPasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } + } diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/springsecuritythymeleaf/ViewControllerIntegrationTest.java b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/springsecuritythymeleaf/ViewControllerIntegrationTest.java index c87d1bacc3..606a33dcf5 100644 --- a/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/springsecuritythymeleaf/ViewControllerIntegrationTest.java +++ b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/springsecuritythymeleaf/ViewControllerIntegrationTest.java @@ -9,11 +9,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @RunWith(SpringRunner.class) @WebMvcTest +@Import(PasswordEncoderConfiguration.class) public class ViewControllerIntegrationTest { @Autowired diff --git a/spring-security-modules/spring-session/spring-session-jdbc/pom.xml b/spring-security-modules/spring-session/spring-session-jdbc/pom.xml index 64bbce44f2..3cc2b8d18e 100644 --- a/spring-security-modules/spring-session/spring-session-jdbc/pom.xml +++ b/spring-security-modules/spring-session/spring-session-jdbc/pom.xml @@ -28,7 +28,6 @@ com.h2database h2 - ${h2.version} runtime diff --git a/spring-security-modules/spring-session/spring-session-mongodb/pom.xml b/spring-security-modules/spring-session/spring-session-mongodb/pom.xml index 878dfeb690..e34589c75b 100644 --- a/spring-security-modules/spring-session/spring-session-mongodb/pom.xml +++ b/spring-security-modules/spring-session/spring-session-mongodb/pom.xml @@ -37,6 +37,7 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo + ${embed.mongo.version} test @@ -50,4 +51,8 @@ + + 3.2.6 + + \ No newline at end of file diff --git a/spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties b/spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties index 4ee830556a..bae3bfeeab 100644 --- a/spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties +++ b/spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties @@ -1,2 +1,4 @@ #To use a randomly allocated free port during tests to avoid port conflict across tests spring.data.mongodb.port=0 + +spring.mongodb.embedded.version=4.4.9 diff --git a/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/PasswordEncoderConfig.java b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/PasswordEncoderConfig.java new file mode 100644 index 0000000000..d9d0725204 --- /dev/null +++ b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/PasswordEncoderConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.session; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java index 678c98e7eb..d9476d7704 100644 --- a/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java +++ b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java @@ -15,8 +15,8 @@ import org.springframework.security.crypto.password.PasswordEncoder; public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("password")).roles("ADMIN"); + public void configureGlobal(AuthenticationManagerBuilder auth, PasswordEncoder passwordEncoder) throws Exception { + auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("password")).roles("ADMIN"); } @Override @@ -24,8 +24,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { http.httpBasic().and().authorizeRequests().antMatchers("/").hasRole("ADMIN").anyRequest().authenticated(); } - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } } diff --git a/spring-sleuth/README.md b/spring-sleuth/README.md index ebaebde6c9..0740b0f6a6 100644 --- a/spring-sleuth/README.md +++ b/spring-sleuth/README.md @@ -5,3 +5,4 @@ This module contains articles about Spring Cloud Sleuth ### Relevant articles: - [Spring Cloud Sleuth in a Monolith Application](https://www.baeldung.com/spring-cloud-sleuth-single-application) +- [Get Current Trace ID in Spring Cloud Sleuth](https://www.baeldung.com/spring-cloud-sleuth-get-trace-id) diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md b/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md new file mode 100644 index 0000000000..3a2b74af70 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/README.md @@ -0,0 +1,5 @@ +# This is a sample on how we can merge the OpenApi code generation with the a custom annotation using ConstraintValidator + +### Relevant Articles: + +- [Custom Validation with Swagger Codegen](https://www.baeldung.com/java-swagger-custom-validation) diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml new file mode 100644 index 0000000000..336cb0da74 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + com.example + custom-validations-opeanpi-codegen + 0.0.1-SNAPSHOT + custom-validations-opeanpi-codegen + Demo project for Swagger Custom Validations Codegen + + + org.springframework.boot + spring-boot-starter-parent + 2.5.4 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.hibernate + hibernate-validator + 6.0.10.Final + + + javax.validation + validation-api + 2.0.1.Final + + + org.openapitools + openapi-generator + 3.3.4 + + + io.springfox + springfox-oas + ${springfox-version} + + + io.springfox + springfox-swagger-ui + ${springfox-version} + + + com.fasterxml.jackson.core + jackson-databind + 2.10.0.pr3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.openapitools + openapi-generator-maven-plugin + 5.1.0 + + + + generate + + + + ${project.basedir}/src/main/resources/petstore.yml + + spring + com.baeldung.openapi.api + com.baeldung.openapi.model + + ApiUtil.java + + + false + java8-localdatetime + + + src/main/resources/openapi/templates + + + + + + + + + + 11 + 3.0.0 + + + \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/Application.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java similarity index 59% rename from guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/Application.java rename to spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java index 01ccf519b3..5a6372ba22 100644 --- a/guest/slf4j/guide/slf4j-log4j/src/main/java/com/stackify/slf4j/guide/Application.java +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/PetstoreApplication.java @@ -1,12 +1,13 @@ -package com.stackify.slf4j.guide; +package com.baeldung.openapi.petstore; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class Application { +public class PetstoreApplication { public static void main(String[] args) { - SpringApplication.run(Application.class, args); + SpringApplication.run(PetstoreApplication.class, args); } + } diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java new file mode 100644 index 0000000000..081d0cb6f9 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetController.java @@ -0,0 +1,17 @@ +package com.baeldung.openapi.petstore.controller; + +import com.baeldung.openapi.api.PetsApi; +import com.baeldung.openapi.model.Pet; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; + +import java.util.Arrays; +import java.util.List; + +@Controller +public class PetController implements PetsApi { + + public ResponseEntity> findPetsByName(String name) { + return ResponseEntity.ok(Arrays.asList(new Pet().id(1L).name(name))); + } +} diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java new file mode 100644 index 0000000000..cf243dbb46 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/controller/PetControllerAdvice.java @@ -0,0 +1,20 @@ +package com.baeldung.openapi.petstore.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import javax.validation.ConstraintViolationException; + +@ControllerAdvice +public class PetControllerAdvice { + + @ResponseBody + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(ConstraintViolationException.class) + public void handleConstraintViolationException() { + + } +} diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Capitalized.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Capitalized.java new file mode 100644 index 0000000000..de83297c53 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/Capitalized.java @@ -0,0 +1,22 @@ +package com.baeldung.openapi.petstore.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = {CapitalizedValidator.class}) +@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Capitalized { + + String message() default "Name should be capitalized."; + + boolean required() default true; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String[] values() default {}; +} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CapitalizedValidator.java b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CapitalizedValidator.java new file mode 100644 index 0000000000..969dc0c56c --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/java/com/baeldung/openapi/petstore/validation/CapitalizedValidator.java @@ -0,0 +1,35 @@ +package com.baeldung.openapi.petstore.validation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +public class CapitalizedValidator implements ConstraintValidator { + + private Capitalized uppercaseAnnotation; + + public void initialize(Capitalized constraintAnnotation) { + this.uppercaseAnnotation = constraintAnnotation; + } + + @Override + public boolean isValid(String nameField, ConstraintValidatorContext context) { + String correctName = buildCorrectName(nameField); + if (uppercaseAnnotation.required() + && (Objects.isNull(nameField) || nameField.isBlank() + || !correctName.equals(nameField))) { + context = context + .buildConstraintViolationWithTemplate(this.uppercaseAnnotation.message()) + .addConstraintViolation(); + context.disableDefaultConstraintViolation(); + return false; + } + return true; + } + + private String buildCorrectName(String nameField) { + String upCase = String.valueOf(nameField.charAt(0)).toUpperCase(); + String lowCase = nameField.substring(1).toLowerCase(); + return upCase.concat(lowCase); + } +} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties new file mode 100644 index 0000000000..d5e4d42eb8 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/application.properties @@ -0,0 +1 @@ +openapi.petStore.base-path=/ diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache new file mode 100644 index 0000000000..34f4afac3a --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache @@ -0,0 +1,150 @@ +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://com.baeldung.openapi-generator.tech) ({{{generatorVersion}}}). + * https://com.baeldung.openapi-generator.tech + * Do not edit the class manually. + */ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import io.swagger.annotations.*; +import com.baeldung.openapi.petstore.validation.Capitalized; +{{#jdk8-no-delegate}} +{{#virtualService}} +import io.virtualan.annotation.ApiVirtual; +import io.virtualan.annotation.VirtualService; +{{/virtualService}} +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +{{/jdk8-no-delegate}} +import org.springframework.http.ResponseEntity; +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated; +{{/useBeanValidation}} +{{#vendorExtensions.x-spring-paginated}} +import org.springframework.data.domain.Pageable; +{{/vendorExtensions.x-spring-paginated}} +import org.springframework.web.bind.annotation.*; +{{#jdk8-no-delegate}} + {{^reactive}} +import org.springframework.web.context.request.NativeWebRequest; + {{/reactive}} +{{/jdk8-no-delegate}} +import org.springframework.web.multipart.MultipartFile; +{{#reactive}} +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.springframework.http.codec.multipart.Part; +{{/reactive}} +import springfox.documentation.annotations.ApiIgnore; + +{{#useBeanValidation}} +import javax.validation.Valid; +import javax.validation.constraints.*; +{{/useBeanValidation}} +import java.util.List; +import java.util.Map; +{{#jdk8-no-delegate}} +import java.util.Optional; +{{/jdk8-no-delegate}} +{{^jdk8-no-delegate}} + {{#useOptional}} +import java.util.Optional; + {{/useOptional}} +{{/jdk8-no-delegate}} +{{#async}} +import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}}; +{{/async}} +{{>generatedAnnotation}} +{{#useBeanValidation}} +@Validated +{{/useBeanValidation}} +@Api(value = "{{{baseName}}}", tags = "All") +{{#operations}} +{{#virtualService}} +@VirtualService +{{/virtualService}} +public interface {{classname}} { +{{#jdk8-default-interface}} + {{^isDelegate}} + {{^reactive}} + + default Optional getRequest() { + return Optional.empty(); + } + {{/reactive}} + {{/isDelegate}} + {{#isDelegate}} + + default {{classname}}Delegate getDelegate() { + return new {{classname}}Delegate() {}; + } + {{/isDelegate}} +{{/jdk8-default-interface}} +{{#operation}} + + /** + * {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}} + {{#notes}} + * {{.}} + {{/notes}} + * + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} + * or {{/-last}}{{/responses}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#virtualService}} + @ApiVirtual + {{/virtualService}} + @ApiOperation(value = "{{{summary}}}", nickname = "{{{operationId}}}", notes = "{{{notes}}}"{{#returnBaseType}}, response = {{{returnBaseType}}}.class{{/returnBaseType}}{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { + {{#authMethods}}{{#isOAuth}}@Authorization(value = "{{name}}", scopes = { + {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}}, + {{/-last}}{{/scopes}} }){{^-last}},{{/-last}}{{/isOAuth}} + {{^isOAuth}}@Authorization(value = "{{name}}"){{^-last}},{{/-last}} + {{/isOAuth}}{{/authMethods}} }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} }) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}} }) + {{#implicitHeaders}} + @ApiImplicitParams({ + {{#headerParams}} + {{>implicitHeader}} + {{/headerParams}} + }) + {{/implicitHeaders}} + @RequestMapping( + method = RequestMethod.{{httpMethod}}, + value = "{{{path}}}"{{#singleContentTypes}}{{#hasProduces}}, + produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}}, + consumes = "{{{vendorExtensions.x-contentType}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}}, + produces = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }{{/hasProduces}}{{#hasConsumes}}, + consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}} + ) + {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},{{/-last}}{{#-last}}{{#reactive}}, {{/reactive}}{{/-last}}{{/allParams}}{{#reactive}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}}{{#unhandledException}} throws Exception{{/unhandledException}} { + {{#delegate-method}} + return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}}); + } + + // Override this method + {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} { + {{/delegate-method}} + {{^isDelegate}} + {{>methodBody}} + {{/isDelegate}} + {{#isDelegate}} + return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}}); + {{/isDelegate}} + }{{/jdk8-default-interface}} + +{{/operation}} +} +{{/operations}} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache new file mode 100644 index 0000000000..e3c19c6474 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache @@ -0,0 +1,26 @@ +{{{ vendorExtensions.x-constraints }}} +{{#errorMessage}}@Mandatory(errorMessage="{{{pattern}}}") {{/errorMessage}} +{{#pattern}}@Pattern(regexp="{{{pattern}}}") {{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}},max={{maxLength}}) {{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}},max={{maxItems}}) {{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{! +@Email: useBeanValidation set && isEmail && java8 set +}}{{#useBeanValidation}}{{#isEmail}}{{#java8}}@javax.validation.constraints.Email{{/java8}}{{/isEmail}}{{/useBeanValidation}}{{! +@Email: performBeanValidation set && isEmail && not java8 set +}}{{#performBeanValidation}}{{#isEmail}}{{^java8}}@org.hibernate.validator.constraints.Email{{/java8}}{{/isEmail}}{{/performBeanValidation}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}}@Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L) {{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache new file mode 100644 index 0000000000..e21bd9ff4b --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache @@ -0,0 +1 @@ +{{#isCookieParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#enumVars}}{{#lambdaEscapeDoubleQuote}}{{{value}}}{{/lambdaEscapeDoubleQuote}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/enumVars}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}) @CookieValue("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isCookieParam}} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache new file mode 100644 index 0000000000..3cdae7f3cc --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache @@ -0,0 +1,31 @@ +class {{classname}} { + /// The underlying value of this enum member. + {{dataType}} value; + + {{classname}}._internal(this.value); + {{ vendorExtensions.x-enum-varnames }} + {{ vendorExtensions.x-enum-descriptions }} + {{#allowableValues}} + {{#enumVars}} + {{#description}} + /// {{description}} + {{/description}} + static {{classname}} {{name}} = {{classname}}._internal({{{value}}}); + {{/enumVars}} + {{/allowableValues}} + + {{classname}}.fromJson(dynamic data) { + switch (data) { + {{#allowableValues}} + {{#enumVars}} + case {{{value}}}: value = data; break; + {{/enumVars}} + {{/allowableValues}} + default: throw('Unknown enum value to decode: $data'); + } + } + + static dynamic encode({{classname}} data) { + return data.value; + } +} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache new file mode 100644 index 0000000000..4546a811ef --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache @@ -0,0 +1,42 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import com.fasterxml.jackson.databind.annotation.*; +import com.fasterxml.jackson.annotation.*; +import com.baeldung.openapi.petstore.validation.Capitalized; +{{^supportJava6}} +import java.util.Objects; +import java.util.Arrays; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.lang3.ObjectUtils; +{{/supportJava6}} +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}} +{{/model}} +{{/models}} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache new file mode 100644 index 0000000000..29f27bd851 --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache @@ -0,0 +1,68 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} +{{#gson}} +import java.io.IOException; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +{{/gson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} +@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{dataType}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue{{#jackson}}({{{dataType}}} value){{/jackson}}{{^jackson}}(String text){{/jackson}} { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if ({{#jackson}}b.value.equals(value){{/jackson}}{{^jackson}}String.valueOf(b.value).equals(text){{/jackson}}) { + return b; + } + } + throw new UlpValidationException(UlpBundleKey.{{vendorExtensions.x-enum-invalidtag}}); + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{#isNumber}}BigDecimal value = new BigDecimal(jsonReader.nextDouble()){{/isNumber}}{{^isNumber}}{{#isInteger}}Integer value {{/isInteger}}{{^isInteger}}String value {{/isInteger}}= jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}nextString(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#jackson}}value{{/jackson}}{{^jackson}}String.valueOf(value){{/jackson}}); + } + } +{{/gson}} +} \ No newline at end of file diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml new file mode 100644 index 0000000000..c5fbd830bb --- /dev/null +++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/petstore.yml @@ -0,0 +1,65 @@ +openapi: 3.0.1 +info: + version: "1.0" + title: PetStore +paths: + /pets: + post: + tags: + - pet + summary: Add a new pet to the store + description: Add a new pet to the store + operationId: addPet + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + responses: + '201': + description: default response, returning the new pet id + content: + application/json: + schema: + type: integer + '400': + description: Invalid input + get: + tags: + - pet + summary: Finds Pets by name + description: 'Find pets by name' + operationId: findPetsByName + parameters: + - name: name + in: query + schema: + type: string + description: Tags to filter by + x-constraints: "@Capitalized(required = true)" + responses: + '200': + description: default response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid name value +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + x-constraints: "@Capitalized(required = true)" \ No newline at end of file diff --git a/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml index 3e2bae73e2..2afde0b07d 100644 --- a/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml +++ b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml @@ -4,16 +4,18 @@ 4.0.0 com.baeldung spring-openapi-generator-api-client - jar - spring-openapi-generator-api-client 0.0.1-SNAPSHOT + spring-openapi-generator-api-client + jar https://github.com/openapitools/openapi-generator OpenAPI Java + scm:git:git@github.com:openapitools/openapi-generator.git scm:git:git@github.com:openapitools/openapi-generator.git https://github.com/openapitools/openapi-generator + Unlicense @@ -21,6 +23,7 @@ repo + OpenAPI-Generator Contributors diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml index c9ba912feb..66e9d1dda2 100644 --- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml +++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml @@ -8,11 +8,13 @@ jar https://github.com/swagger-api/swagger-codegen Swagger Java + scm:git:git@github.com:swagger-api/swagger-codegen.git scm:git:git@github.com:swagger-api/swagger-codegen.git https://github.com/swagger-api/swagger-codegen + Unlicense @@ -20,6 +22,7 @@ repo + Swagger diff --git a/spring-vertx/pom.xml b/spring-vertx/pom.xml index bd2dfa6cf6..e24bb3f1ee 100644 --- a/spring-vertx/pom.xml +++ b/spring-vertx/pom.xml @@ -47,15 +47,6 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - 3.4.1 diff --git a/spring-web-modules/pom.xml b/spring-web-modules/pom.xml index e498185c5e..d66d9cb35a 100644 --- a/spring-web-modules/pom.xml +++ b/spring-web-modules/pom.xml @@ -20,6 +20,7 @@ spring-mvc-basics-2 spring-mvc-basics-3 spring-mvc-basics-4 + spring-mvc-basics-5 spring-mvc-crash spring-mvc-forms-jsp spring-mvc-forms-thymeleaf @@ -29,6 +30,7 @@ spring-mvc-views spring-mvc-webflow spring-mvc-xml + spring-mvc-xml-2 spring-rest-angular spring-rest-http spring-rest-http-2 @@ -42,7 +44,10 @@ spring-thymeleaf spring-thymeleaf-2 spring-thymeleaf-3 + spring-thymeleaf-4 + spring-thymeleaf-5 spring-boot-jsp + spring-web-url - \ No newline at end of file + diff --git a/spring-web-modules/spring-5-mvc/pom.xml b/spring-web-modules/spring-5-mvc/pom.xml index 79a4f73ace..23bcb00801 100644 --- a/spring-web-modules/spring-5-mvc/pom.xml +++ b/spring-web-modules/spring-5-mvc/pom.xml @@ -81,12 +81,6 @@ ${project.basedir}/src/test/kotlin - - - org.springframework.boot - spring-boot-maven-plugin - - diff --git a/spring-web-modules/spring-boot-jsp/pom.xml b/spring-web-modules/spring-boot-jsp/pom.xml index 222facd100..b9b4a97e6b 100644 --- a/spring-web-modules/spring-boot-jsp/pom.xml +++ b/spring-web-modules/spring-boot-jsp/pom.xml @@ -92,7 +92,6 @@ 1.2 2.4.4 - 2.22.2 \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/test/resources/logback-test.xml b/spring-web-modules/spring-boot-jsp/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-2/README.md b/spring-web-modules/spring-mvc-basics-2/README.md index cbc9f93e93..87ce9984a2 100644 --- a/spring-web-modules/spring-mvc-basics-2/README.md +++ b/spring-web-modules/spring-mvc-basics-2/README.md @@ -10,7 +10,4 @@ This module contains articles about Spring MVC - [Guide to Spring Email](https://www.baeldung.com/spring-email) - [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/spring-email-templates) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) -- [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) -- [Spring @RequestParam vs @PathVariable Annotations](https://www.baeldung.com/spring-requestparam-vs-pathvariable) -- More articles: [[more -->]](/spring-mvc-basics-3) -- More articles: [[<-- prev]](/spring-mvc-basics) +- More articles: [[<-- prev]](../spring-mvc-basics)[[more -->]](../spring-mvc-basics-3) diff --git a/spring-web-modules/spring-mvc-basics-3/README.md b/spring-web-modules/spring-mvc-basics-3/README.md index 074c60152c..c9fb14d42c 100644 --- a/spring-web-modules/spring-mvc-basics-3/README.md +++ b/spring-web-modules/spring-mvc-basics-3/README.md @@ -5,12 +5,8 @@ This module contains articles about Spring MVC ## Relevant articles: - [How to Read HTTP Headers in Spring REST Controllers](https://www.baeldung.com/spring-rest-http-headers) - [A Custom Data Binder in Spring MVC](https://www.baeldung.com/spring-mvc-custom-data-binder) -- [Validating Lists in a Spring Controller](https://www.baeldung.com/spring-validate-list-controller) - [Spring Validation Message Interpolation](https://www.baeldung.com/spring-validation-message-interpolation) -- [Using a Slash Character in Spring URLs](https://www.baeldung.com/spring-slash-character-in-url) - [Using Enums as Request Parameters in Spring](https://www.baeldung.com/spring-enum-request-param) -- [Excluding URLs for a Filter in a Spring Web Application](https://www.baeldung.com/spring-exclude-filter) - [Guide to Flash Attributes in a Spring Web Application](https://www.baeldung.com/spring-web-flash-attributes) -- [Handling URL Encoded Form Data in Spring REST](https://www.baeldung.com/spring-url-encoded-form-data) - [Reading HttpServletRequest Multiple Times in Spring](https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times) -- More articles: [[<-- prev]](/spring-mvc-basics-2)[[more -->]](/spring-mvc-basics-4) +- More articles: [[<-- prev]](../spring-mvc-basics-2)[[more -->]](../spring-mvc-basics-4) diff --git a/spring-web-modules/spring-mvc-basics-3/pom.xml b/spring-web-modules/spring-mvc-basics-3/pom.xml index f9710ff2d1..7e0d741619 100644 --- a/spring-web-modules/spring-mvc-basics-3/pom.xml +++ b/spring-web-modules/spring-mvc-basics-3/pom.xml @@ -130,7 +130,6 @@ 3.1.1 3.3.7-1 2.2 - 18.0 3.1.7 4.5.8 diff --git a/spring-web-modules/spring-mvc-basics-4/README.md b/spring-web-modules/spring-mvc-basics-4/README.md index f003f7df01..e3211a87df 100644 --- a/spring-web-modules/spring-mvc-basics-4/README.md +++ b/spring-web-modules/spring-mvc-basics-4/README.md @@ -10,4 +10,5 @@ The "REST With Spring" Classes: https://bit.ly/restwithspring - [Spring Optional Path variables](https://www.baeldung.com/spring-optional-path-variables) - [JSON Parameters with Spring MVC](https://www.baeldung.com/spring-mvc-send-json-parameters) - [How to Set JSON Content Type In Spring MVC](https://www.baeldung.com/spring-mvc-set-json-content-type) -- More articles: [[<-- prev]](/spring-mvc-basics-3) +- [Validating Lists in a Spring Controller](https://www.baeldung.com/spring-validate-list-controller) +- More articles: [[<-- prev]](../spring-mvc-basics-3)[[next -->]](../spring-mvc-basics-5) diff --git a/spring-web-modules/spring-mvc-basics-4/pom.xml b/spring-web-modules/spring-mvc-basics-4/pom.xml index 067d1ed3b1..376e13ed72 100644 --- a/spring-web-modules/spring-mvc-basics-4/pom.xml +++ b/spring-web-modules/spring-mvc-basics-4/pom.xml @@ -23,6 +23,10 @@ org.springframework spring-web + + org.springframework.boot + spring-boot-starter-validation + javax.servlet javax.servlet-api diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java diff --git a/spring-web-modules/spring-mvc-basics-5/.gitignore b/spring-web-modules/spring-mvc-basics-5/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-5/README.md b/spring-web-modules/spring-mvc-basics-5/README.md new file mode 100644 index 0000000000..880db7aacd --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/README.md @@ -0,0 +1,16 @@ +## Spring MVC Basics + +This module contains articles about the basics of Spring MVC. Articles about more specific areas of Spring MVC have +their own module. + +### The Course +The "REST With Spring" Classes: https://bit.ly/restwithspring + +### Relevant Articles: +- [Spring MVC Custom Validation](https://www.baeldung.com/spring-mvc-custom-validator) +- [Using Spring @ResponseStatus to Set HTTP Status Code](https://www.baeldung.com/spring-response-status) +- [Spring MVC and the @ModelAttribute Annotation](https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation) +- [The HttpMediaTypeNotAcceptableException in Spring MVC](https://www.baeldung.com/spring-httpmediatypenotacceptable) +- [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) +- [Spring @RequestParam vs @PathVariable Annotations](https://www.baeldung.com/spring-requestparam-vs-pathvariable) +- More articles: [[<-- prev]](../spring-mvc-basics-4) diff --git a/spring-web-modules/spring-mvc-basics-5/pom.xml b/spring-web-modules/spring-mvc-basics-5/pom.xml new file mode 100644 index 0000000000..3b64f15c4b --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + spring-mvc-basics-5 + 0.1-SNAPSHOT + spring-mvc-basics-5 + jar + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + + org.apache.tomcat.embed + tomcat-embed-jasper + + + javax.servlet + jstl + + + org.springframework.boot + spring-boot-starter-test + test + + + + + spring-mvc-basics + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.Application + JAR + + + + + + \ No newline at end of file diff --git a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/Application.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/Application.java similarity index 57% rename from guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/Application.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/Application.java index 01ccf519b3..d58049fb35 100644 --- a/guest/slf4j/guide/slf4j-logback/src/main/java/com/stackify/slf4j/guide/Application.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/Application.java @@ -1,12 +1,11 @@ -package com.stackify.slf4j.guide; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserController.java similarity index 91% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserController.java index fddd8baabb..c71d862941 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserController.java @@ -1,6 +1,4 @@ -package com.baeldung.web.controller; - -import javax.validation.Valid; +package com.baeldung.customvalidator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -8,7 +6,7 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; -import com.baeldung.model.NewUserForm; +import javax.validation.Valid; @Controller public class NewUserController { diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserForm.java similarity index 97% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserForm.java index b4fe82ab4a..0685f0373c 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/NewUserForm.java @@ -1,4 +1,4 @@ -package com.baeldung.model; +package com.baeldung.customvalidator; import com.baeldung.customvalidator.FieldsValueMatch; diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhone.java similarity index 90% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhone.java index 8cea915e6e..25676e49ec 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhone.java @@ -1,4 +1,4 @@ -package com.baeldung.model; +package com.baeldung.customvalidator; import com.baeldung.customvalidator.ContactNumberConstraint; diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java similarity index 91% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java index 73e1e4bb25..be347a6777 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.customvalidator; import javax.validation.Valid; @@ -8,8 +8,6 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; -import com.baeldung.model.ValidatedPhone; - @Controller public class ValidatedPhoneController { diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java new file mode 100644 index 0000000000..0ec3c5c374 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java @@ -0,0 +1,61 @@ +package com.baeldung.modelattribute; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Employee { + + private long id; + private String name; + private String contactNumber; + private String workingArea; + + public Employee() { + super(); + } + + public Employee(final long id, final String name, final String contactNumber, final String workingArea) { + this.id = id; + this.name = name; + this.contactNumber = contactNumber; + this.workingArea = workingArea; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getContactNumber() { + return contactNumber; + } + + public void setContactNumber(final String contactNumber) { + this.contactNumber = contactNumber; + } + + public String getWorkingArea() { + return workingArea; + } + + public void setWorkingArea(final String workingArea) { + this.workingArea = workingArea; + } + + @Override + public String toString() { + return "Employee [id=" + id + ", name=" + name + ", contactNumber=" + contactNumber + ", workingArea=" + workingArea + "]"; + } + +} diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/EmployeeController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/EmployeeController.java new file mode 100644 index 0000000000..7fc9f56dce --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/EmployeeController.java @@ -0,0 +1,58 @@ +package com.baeldung.modelattribute; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.ui.ModelMap; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import java.util.HashMap; +import java.util.Map; + +@Controller +public class EmployeeController { + + Map employeeMap = new HashMap<>(); + + @ModelAttribute("employees") + public void initEmployees() { + employeeMap.put(1L, new Employee(1L, "John", "223334411", "rh")); + employeeMap.put(2L, new Employee(2L, "Peter", "22001543", "informatics")); + employeeMap.put(3L, new Employee(3L, "Mike", "223334411", "admin")); + } + + @RequestMapping(value = "/employee", method = RequestMethod.GET) + public ModelAndView showForm() { + return new ModelAndView("employeeHome", "employee", new Employee()); + } + + @RequestMapping(value = "/employee/{Id}", produces = { "application/json", "application/xml" }, method = RequestMethod.GET) + public @ResponseBody Employee getEmployeeById(@PathVariable final Long Id) { + return employeeMap.get(Id); + } + + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) + public String submit(@ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { + if (result.hasErrors()) { + return "error"; + } + model.addAttribute("name", employee.getName()); + model.addAttribute("contactNumber", employee.getContactNumber()); + model.addAttribute("workingArea", employee.getWorkingArea()); + model.addAttribute("id", employee.getId()); + + employeeMap.put(employee.getId(), employee); + + return "employeeView"; + } + + @ModelAttribute + public void addAttributes(final Model model) { + model.addAttribute("msg", "Welcome to the Netherlands!"); + } +} diff --git a/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestparam/RequestParamController.java similarity index 98% rename from spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java rename to spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestparam/RequestParamController.java index eb445f7801..a6b3a885e5 100644 --- a/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestparam/RequestParamController.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.requestparam; +package com.baeldung.requestparam; import java.util.List; import java.util.Map; diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/Book.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/Book.java new file mode 100644 index 0000000000..8e603040dc --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/Book.java @@ -0,0 +1,42 @@ +package com.baeldung.responsestatus; + +public class Book { + + private int id; + private String author; + private String title; + + public Book() { + } + + public Book(int id, String author, String title) { + this.id = id; + this.author = author; + this.title = title; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + +} diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/ResponseStatusRestController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/ResponseStatusRestController.java new file mode 100644 index 0000000000..e3ace14b93 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/responsestatus/ResponseStatusRestController.java @@ -0,0 +1,47 @@ +package com.baeldung.responsestatus; + +import java.util.concurrent.ThreadLocalRandom; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +public class ResponseStatusRestController { + + @GetMapping("/teapot") + @ResponseStatus(HttpStatus.I_AM_A_TEAPOT) + public void teaPot() { + } + + @GetMapping("empty") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void emptyResponse() { + } + + @GetMapping("empty-no-responsestatus") + public void emptyResponseWithoutResponseStatus() { + } + + @PostMapping("create") + @ResponseStatus(HttpStatus.CREATED) + public Book createEntity() { + // here we would create and persist an entity + int randomInt = ThreadLocalRandom.current() + .nextInt(1, 100); + Book entity = new Book(randomInt, "author" + randomInt, "title" + randomInt); + return entity; + } + + @PostMapping("create-no-responsestatus") + public Book createEntityWithoutResponseStatus() { + // here we would create and persist an entity + int randomInt = ThreadLocalRandom.current() + .nextInt(1, 100); + Book entity = new Book(randomInt, "author" + randomInt, "title" + randomInt); + return entity; + } +} diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/spring/web/config/WebConfig.java new file mode 100644 index 0000000000..53865d02d5 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -0,0 +1,49 @@ +package com.baeldung.spring.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.PathResourceResolver; +import org.springframework.web.servlet.view.BeanNameViewResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + registry.addViewController("/") + .setViewName("index"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(2); + return bean; + } + + /** Static resource locations */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**") + .addResourceLocations("/", "/resources/") + .setCachePeriod(3600) + .resourceChain(true) + .addResolver(new PathResourceResolver()); + } + + @Bean + public BeanNameViewResolver beanNameViewResolver(){ + BeanNameViewResolver beanNameViewResolver = new BeanNameViewResolver(); + beanNameViewResolver.setOrder(1); + return beanNameViewResolver; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties new file mode 100644 index 0000000000..935f91554b --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties @@ -0,0 +1 @@ +server.servlet.context-path=/spring-mvc-basics diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeHome.jsp new file mode 100644 index 0000000000..fa5812faea --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeHome.jsp @@ -0,0 +1,33 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> + + + +Form Example - Register an Employee + + +

Welcome, Enter The Employee Details

+ + + + + + + + + + + + + + + + + + +
Name
Id
Contact Number
+
+ + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeView.jsp new file mode 100644 index 0000000000..9a9b879a35 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/employeeView.jsp @@ -0,0 +1,25 @@ +<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> + + +Spring MVC Form Handling + + + +

Submitted Employee Information

+

${msg}

+ + + + + + + + + + + + + +
Name :${name}
ID :${id}
Contact Number :${contactNumber}
+ + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/index.jsp b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/index.jsp new file mode 100644 index 0000000000..4f4eb0068d --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/index.jsp @@ -0,0 +1,7 @@ + + + + +

This is the body of the index view

+ + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/phoneHome.jsp b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/phoneHome.jsp new file mode 100644 index 0000000000..ebc9052639 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/phoneHome.jsp @@ -0,0 +1,38 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + + + Sample Form + + + + +
+ +

Phone Number

+
${message}
+ + + + + + +
+ + +
+
+ + diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/userHome.jsp b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/userHome.jsp new file mode 100644 index 0000000000..38c08d5a18 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/webapp/WEB-INF/view/userHome.jsp @@ -0,0 +1,55 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + + + User Form + + + +
+ +

New User

+
${message}
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+
+ + diff --git a/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..f475e5d626 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } +} diff --git a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/ClassValidationMvcIntegrationTest.java similarity index 98% rename from spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/ClassValidationMvcIntegrationTest.java index 24182f492a..f06c8d7002 100644 --- a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/ClassValidationMvcIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.customvalidator; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; diff --git a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/CustomMVCValidatorIntegrationTest.java similarity index 97% rename from spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/CustomMVCValidatorIntegrationTest.java index 11b72e1650..104915f9ab 100644 --- a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/customvalidator/CustomMVCValidatorIntegrationTest.java @@ -1,10 +1,4 @@ -package com.baeldung.web.controller; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; +package com.baeldung.customvalidator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,6 +7,12 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + public class CustomMVCValidatorIntegrationTest { private MockMvc mockMvc; diff --git a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java similarity index 100% rename from spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java diff --git a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/modelattribute/EmployeeControllerModelAttributeIntegrationTest.java similarity index 98% rename from spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/modelattribute/EmployeeControllerModelAttributeIntegrationTest.java index 5195adabd5..ffe2034a48 100644 --- a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/modelattribute/EmployeeControllerModelAttributeIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.modelattribute; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; diff --git a/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/responsestatus/ResponseStatusRestControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/responsestatus/ResponseStatusRestControllerIntegrationTest.java new file mode 100644 index 0000000000..cb5f1925bf --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/responsestatus/ResponseStatusRestControllerIntegrationTest.java @@ -0,0 +1,52 @@ +package com.baeldung.responsestatus; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class ResponseStatusRestControllerIntegrationTest { + + private MockMvc mockMvc; + + @BeforeEach + public void setup() { + this.mockMvc = MockMvcBuilders.standaloneSetup(new ResponseStatusRestController()) + .build(); + } + + @Test + public void whenTeapotEndpointCalled_thenTeapotResponseObtained() throws Exception { + this.mockMvc.perform(get("/teapot")) + .andExpect(status().isIAmATeapot()); + } + + @Test + public void whenEmptyNoContentEndpointCalled_thenNoContentResponseObtained() throws Exception { + this.mockMvc.perform(get("/empty")) + .andExpect(status().isNoContent()); + } + + @Test + public void whenEmptyWithoutResponseStatusEndpointCalled_then200ResponseObtained() throws Exception { + this.mockMvc.perform(get("/empty-no-responsestatus")) + .andExpect(status().isOk()); + } + + @Test + public void whenCreateWithCreatedEndpointCalled_thenCreatedResponseObtained() throws Exception { + this.mockMvc.perform(post("/create")) + .andExpect(status().isCreated()); + } + + @Test + public void whenCreateWithoutResponseStatusEndpointCalled_thenCreatedResponseObtained() throws Exception { + this.mockMvc.perform(post("/create-no-responsestatus")) + .andExpect(status().isOk()); + } + +} diff --git a/spring-web-modules/spring-mvc-basics-5/src/test/resources/logback-test.xml b/spring-web-modules/spring-mvc-basics-5/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics/README.md b/spring-web-modules/spring-mvc-basics/README.md index 49d23aef25..cce4eb4f59 100644 --- a/spring-web-modules/spring-mvc-basics/README.md +++ b/spring-web-modules/spring-mvc-basics/README.md @@ -14,8 +14,4 @@ The "REST With Spring" Classes: https://bit.ly/restwithspring - [Guide to Spring Handler Mappings](https://www.baeldung.com/spring-handler-mappings) - [Spring MVC Content Negotiation](https://www.baeldung.com/spring-mvc-content-negotiation-json-xml) - [Spring @RequestMapping New Shortcut Annotations](https://www.baeldung.com/spring-new-requestmapping-shortcuts) -- [Spring MVC Custom Validation](https://www.baeldung.com/spring-mvc-custom-validator) -- [Using Spring @ResponseStatus to Set HTTP Status Code](https://www.baeldung.com/spring-response-status) -- [Spring MVC and the @ModelAttribute Annotation](https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation) -- [The HttpMediaTypeNotAcceptableException in Spring MVC](https://www.baeldung.com/spring-httpmediatypenotacceptable) -- More articles: [[more -->]](/spring-mvc-basics-2) +- More articles: [[more -->]](../spring-mvc-basics-2) diff --git a/spring-web-modules/spring-mvc-basics/pom.xml b/spring-web-modules/spring-mvc-basics/pom.xml index a91f4004ff..ccd6773e6f 100644 --- a/spring-web-modules/spring-mvc-basics/pom.xml +++ b/spring-web-modules/spring-mvc-basics/pom.xml @@ -20,10 +20,6 @@ org.springframework.boot spring-boot-starter-web
- - org.springframework.boot - spring-boot-starter-validation - commons-fileupload commons-fileupload diff --git a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java index e1987f8345..7b0d2ddf36 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -53,7 +53,7 @@ public class WebConfig implements WebMvcConfigurer { /** Static resource locations including themes*/ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**/*") + registry.addResourceHandler("/resources/**") .addResourceLocations("/", "/resources/") .setCachePeriod(3600) .resourceChain(true) @@ -118,8 +118,7 @@ public class WebConfig implements WebMvcConfigurer { */ @Override public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { - configurer.favorPathExtension(true) - .favorParameter(true) + configurer.favorParameter(true) .parameterName("mediaType") .ignoreAcceptHeader(false) .useRegisteredExtensionsOnly(false) diff --git a/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties index b8a9be0b40..a1ab6f1fe4 100644 --- a/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties +++ b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties @@ -1,7 +1,5 @@ server.servlet.context-path=/spring-mvc-basics ### Content Negotiation (already defined programatically) -spring.mvc.pathmatch.use-suffix-pattern=true -#spring.mvc.contentnegotiation.favor-path-extension=true #spring.mvc.contentnegotiation.favor-parameter=true -#spring.mvc.contentnegotiation.parameter-name=mediaType +#spring.mvc.contentnegotiation.parameter-name=mediaType \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java index 4ccba79f9c..0b9f26ab16 100644 --- a/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java @@ -19,20 +19,6 @@ public class EmployeeControllerContentNegotiationIntegrationTest { @Autowired private MockMvc mockMvc; - @Test - public void whenEndpointUsingJsonSuffixCalled_thenJsonResponseObtained() throws Exception { - this.mockMvc.perform(get("/employee/1.json")) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)); - } - - @Test - public void whenEndpointUsingXmlSuffixCalled_thenXmlResponseObtained() throws Exception { - this.mockMvc.perform(get("/employee/1.xml")) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)); - } - @Test public void whenEndpointUsingJsonParameterCalled_thenJsonResponseObtained() throws Exception { this.mockMvc.perform(get("/employee/1?mediaType=json")) diff --git a/spring-web-modules/spring-mvc-basics/src/test/resources/logback-test.xml b/spring-web-modules/spring-mvc-basics/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-crash/pom.xml b/spring-web-modules/spring-mvc-crash/pom.xml index 9574eff2a4..2b7b79666d 100644 --- a/spring-web-modules/spring-mvc-crash/pom.xml +++ b/spring-web-modules/spring-mvc-crash/pom.xml @@ -142,7 +142,6 @@ 6.0.10.Final 3.0.1-b08 - 19.0 2.8.0 1.6.1 diff --git a/spring-web-modules/spring-mvc-forms-jsp/pom.xml b/spring-web-modules/spring-mvc-forms-jsp/pom.xml index 707c18fa19..b0269e3344 100644 --- a/spring-web-modules/spring-mvc-forms-jsp/pom.xml +++ b/spring-web-modules/spring-mvc-forms-jsp/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.1-SNAPSHOT spring-mvc-forms-jsp + 0.1-SNAPSHOT spring-mvc-forms-jsp war diff --git a/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java index 3f9de2179a..3d5df0653d 100644 --- a/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java +++ b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java @@ -34,7 +34,7 @@ public class EmployeeController { public @ResponseBody Employee getEmployeeById(@PathVariable final long Id) { return employeeMap.get(Id); } - + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) public String submit(@ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { if (result.hasErrors()) { @@ -65,7 +65,7 @@ public class EmployeeController { @RequestMapping(value = "/employeesContacts/{contactNumber}", method = RequestMethod.GET) @ResponseBody - public ResponseEntity> getEmployeeBycontactNumber(@MatrixVariable(required = true) final String contactNumber) { + public ResponseEntity> getEmployeeByContactNumber(@MatrixVariable(required = true) final String contactNumber) { final List employeesList = new ArrayList(); for (final Map.Entry employeeEntry : employeeMap.entrySet()) { final Employee employee = employeeEntry.getValue(); @@ -84,9 +84,9 @@ public class EmployeeController { @RequestMapping(value = "employeeArea/{workingArea}", method = RequestMethod.GET) @ResponseBody - public ResponseEntity> getEmployeeByWorkingArea(@MatrixVariable final Map> matrixVars) { - final List employeesList = new ArrayList(); - final LinkedList workingArea = matrixVars.get("workingArea"); + public ResponseEntity> getEmployeeByWorkingArea(@MatrixVariable final Map> matrixVars) { + final List employeesList = new ArrayList<>(); + final Collection workingArea = matrixVars.get("workingArea"); for (final Map.Entry employeeEntry : employeeMap.entrySet()) { final Employee employee = employeeEntry.getValue(); for (final String area : workingArea) { diff --git a/spring-web-modules/spring-mvc-java-2/src/test/resources/logback-test.xml b/spring-web-modules/spring-mvc-java-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-mvc-java-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-java/pom.xml b/spring-web-modules/spring-mvc-java/pom.xml index 68b4c74dce..208973eccb 100644 --- a/spring-web-modules/spring-mvc-java/pom.xml +++ b/spring-web-modules/spring-mvc-java/pom.xml @@ -221,7 +221,6 @@ 6.0.10.Final - 19.0 2.2.0 4.4.5 diff --git a/spring-web-modules/spring-mvc-xml-2/.gitignore b/spring-web-modules/spring-mvc-xml-2/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/README.md b/spring-web-modules/spring-mvc-xml-2/README.md new file mode 100644 index 0000000000..05a6172fa1 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/README.md @@ -0,0 +1,14 @@ +## Spring MVC XML + +This module contains articles about Spring MVC with XML configuration + +### The Course + +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: + +- [Exploring SpringMVC’s Form Tag Library](https://www.baeldung.com/spring-mvc-form-tags) +- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) +- [Debugging the Spring MVC 404 “No mapping found for HTTP request” Error](https://www.baeldung.com/spring-mvc-404-error) +- More articles: [[<-- prev]](../spring-mvc-xml) diff --git a/spring-web-modules/spring-mvc-xml-2/pom.xml b/spring-web-modules/spring-mvc-xml-2/pom.xml new file mode 100644 index 0000000000..5910823e95 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + spring-mvc-xml-2 + 0.1-SNAPSHOT + spring-mvc-xml-2 + war + + + com.baeldung + spring-web-modules + 0.0.1-SNAPSHOT + + + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + javax.servlet + jstl + ${jstl.version} + runtime + + + org.hibernate.validator + hibernate-validator + ${hibernate-validator.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + commons-io + commons-io + ${commons-io.version} + + + org.glassfish + javax.el + ${javax.el.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + + + spring-mvc-xml-2 + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + + + + 5.0.2.RELEASE + 1.5.10.RELEASE + 5.1.40 + 4.4.5 + 4.5.2 + 6.0.10.Final + 3.0.1-b08 + 1.6.1 + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfig.java new file mode 100644 index 0000000000..a464717f5d --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@ImportResource("classpath:webMvcConfig.xml") +@Configuration +@ComponentScan +public class ClientWebConfig implements WebMvcConfigurer { + + public ClientWebConfig() { + super(); + } + +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfigJava.java similarity index 96% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfigJava.java index 09c34ccc80..dc8db43e41 100644 --- a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/ClientWebConfigJava.java @@ -6,6 +6,7 @@ import java.util.ResourceBundle; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.context.support.MessageSourceResourceBundle; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; @@ -54,7 +55,7 @@ public class ClientWebConfigJava implements WebMvcConfigurer { return bean; } - + @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java similarity index 100% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/nomapping/GreetingController.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/nomapping/GreetingController.java new file mode 100644 index 0000000000..5016113d30 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/nomapping/GreetingController.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.nomapping; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class GreetingController { + + @RequestMapping(value = "/greeting", method = RequestMethod.GET) + public String get(ModelMap model) { + model.addAttribute("message", "Hello, World!"); + return "greeting"; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationController.java similarity index 79% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationController.java index b77598c113..4768237871 100644 --- a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationController.java @@ -1,12 +1,17 @@ -package com.baeldung.spring.controller; +package com.baeldung.spring.paramsvalidation; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; @Controller @RequestMapping("/public/api/1") diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/Person.java similarity index 98% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/Person.java index 307a36b10f..ed2fa903ef 100644 --- a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/Person.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.form; +package com.baeldung.spring.taglibrary; import java.util.List; diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonController.java similarity index 95% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonController.java index 71d9ad7845..0fcb66f2dd 100644 --- a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonController.java @@ -1,14 +1,5 @@ -package com.baeldung.spring.controller; +package com.baeldung.spring.taglibrary; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import javax.validation.Valid; - -import com.baeldung.spring.form.Person; -import com.baeldung.spring.validator.PersonValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -19,6 +10,12 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + @Controller public class PersonController { diff --git a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonValidator.java similarity index 87% rename from spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java rename to spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonValidator.java index cda756cdfc..9f437429ae 100644 --- a/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java +++ b/spring-web-modules/spring-mvc-xml-2/src/main/java/com/baeldung/spring/taglibrary/PersonValidator.java @@ -1,6 +1,5 @@ -package com.baeldung.spring.validator; +package com.baeldung.spring.taglibrary; -import com.baeldung.spring.form.Person; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-xml-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/resources/messages.properties b/spring-web-modules/spring-mvc-xml-2/src/main/resources/messages.properties new file mode 100644 index 0000000000..a58f51db3e --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/resources/messages.properties @@ -0,0 +1,3 @@ +required.name = Name is required! +NotEmpty.person.password = Password is required! + diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/resources/webMvcConfig.xml b/spring-web-modules/spring-mvc-xml-2/src/main/resources/webMvcConfig.xml new file mode 100644 index 0000000000..5dcdef6ad4 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/resources/webMvcConfig.xml @@ -0,0 +1,40 @@ + + + + + + + + + image/jpeg + image/png + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 0000000000..e27665da95 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/greeting.jsp b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/greeting.jsp new file mode 100644 index 0000000000..ac17c75ab7 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/greeting.jsp @@ -0,0 +1,9 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Greeting + + +

${message}

+ + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/personForm.jsp similarity index 100% rename from spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp rename to spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/personForm.jsp diff --git a/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/personView.jsp similarity index 100% rename from spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp rename to spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/personView.jsp diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/sample.jsp new file mode 100644 index 0000000000..7cc14b5dcd --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/view/sample.jsp @@ -0,0 +1,7 @@ + + + + +

This is the body of the sample view

+ + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..e704d2eba3 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,47 @@ + + + Spring MVC XML Application + + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + com.baeldung.spring + + + + org.springframework.web.context.ContextLoaderListener + + + + + mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + + mvc + / + + + + + 10 + + + index.jsp + + + + /errors + + diff --git a/spring-web-modules/spring-mvc-xml-2/src/main/webapp/index.jsp b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/index.jsp new file mode 100644 index 0000000000..14872cf3ba --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/main/webapp/index.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Spring MVC Examples + + + +

Spring MVC Examples

+ + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..62e34859ee --- /dev/null +++ b/spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.spring.ClientWebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ClientWebConfig.class) +@WebAppConfiguration +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationControllerIntegrationTest.java similarity index 90% rename from spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationControllerIntegrationTest.java index c4332dd879..a71a024e62 100644 --- a/spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-web-modules/spring-mvc-xml-2/src/test/java/com/baeldung/spring/paramsvalidation/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -1,5 +1,6 @@ -package com.baeldung.spring.controller; +package com.baeldung.spring.paramsvalidation; +import com.baeldung.spring.ClientWebConfigJava; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -11,9 +12,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.baeldung.spring.ClientWebConfig; -import com.baeldung.spring.ClientWebConfigJava; - import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -35,13 +33,13 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { @Test public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))) - .andExpect(status().isOk()); + .andExpect(status().isOk()); } @Test public void getNameOfDayByNumberRequestParam_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(15))) - .andExpect(status().isBadRequest()); + .andExpect(status().isBadRequest()); } @Test @@ -52,7 +50,7 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { @Test public void getNameOfDayByPathVariable_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(15))) - .andExpect(status().isBadRequest()); + .andExpect(status().isBadRequest()); } @Test @@ -63,7 +61,7 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { @Test public void validStringRequestParam_whenGetWithTooLongRequestParam_thenReturn400() throws Exception { mockMvc.perform(get("/public/api/1/valid-name").param("name", "asdfghjklqw")) - .andExpect(status().isBadRequest()); + .andExpect(status().isBadRequest()); } @Test diff --git a/spring-web-modules/spring-mvc-xml/README.md b/spring-web-modules/spring-mvc-xml/README.md index 3fbea3626b..3260d91d94 100644 --- a/spring-web-modules/spring-mvc-xml/README.md +++ b/spring-web-modules/spring-mvc-xml/README.md @@ -12,12 +12,10 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Returning Image/Media Data with Spring MVC](https://www.baeldung.com/spring-mvc-image-media-data) - [Geolocation by IP in Java](https://www.baeldung.com/geolocation-by-ip-with-maxmind) - [Guide to JavaServer Pages (JSP)](https://www.baeldung.com/jsp) -- [Exploring SpringMVC’s Form Tag Library](https://www.baeldung.com/spring-mvc-form-tags) - [web.xml vs Initializer with Spring](https://www.baeldung.com/spring-xml-vs-java-config) - [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml) -- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) -- [Debugging the Spring MVC 404 “No mapping found for HTTP request” Error](https://www.baeldung.com/spring-mvc-404-error) - [Introduction to Servlets and Servlet Containers](https://www.baeldung.com/java-servlets-containers-intro) +- More articles: [[more -->]](../spring-mvc-xml-2) ## Spring MVC with XML Configuration Example Project diff --git a/spring-web-modules/spring-mvc-xml/pom.xml b/spring-web-modules/spring-mvc-xml/pom.xml index e67052e0cd..d8d4082219 100644 --- a/spring-web-modules/spring-mvc-xml/pom.xml +++ b/spring-web-modules/spring-mvc-xml/pom.xml @@ -39,11 +39,6 @@ ${jstl.version} runtime
- - org.hibernate.validator - hibernate-validator - ${hibernate-validator.version} - com.fasterxml.jackson.core @@ -142,7 +137,6 @@ 6.0.10.Final 3.0.1-b08 - 19.0 2.8.0 1.6.1 diff --git a/spring-web-modules/spring-rest-angular/pom.xml b/spring-web-modules/spring-rest-angular/pom.xml index e7cb5c8664..36f9694fa1 100644 --- a/spring-web-modules/spring-rest-angular/pom.xml +++ b/spring-web-modules/spring-rest-angular/pom.xml @@ -74,7 +74,6 @@ - 19.0 com.baeldung.web.main.Application diff --git a/spring-web-modules/spring-rest-http-2/README.md b/spring-web-modules/spring-rest-http-2/README.md index 74e55c7c40..bb9175db8c 100644 --- a/spring-web-modules/spring-rest-http-2/README.md +++ b/spring-web-modules/spring-rest-http-2/README.md @@ -1,6 +1,6 @@ ## Spring REST HTTP 2 -This module contains articles about HTTP in REST APIs with Spring +This module contains articles about HTTP in REST APIs with Spring. ### The Course The "REST With Spring 2" Classes: http://bit.ly/restwithspring @@ -10,3 +10,5 @@ The "REST With Spring 2" Classes: http://bit.ly/restwithspring - [How to Turn Off Swagger-ui in Production](https://www.baeldung.com/swagger-ui-turn-off-in-production) - [Setting a Request Timeout for a Spring REST API](https://www.baeldung.com/spring-rest-timeout) - [Long Polling in Spring MVC](https://www.baeldung.com/spring-mvc-long-polling) +- [Guide to UriComponentsBuilder in Spring](https://www.baeldung.com/spring-uricomponentsbuilder) +- More articles: [[<-- prev]](../spring-rest-http) diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/configuration/WebClientConfiguration.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/configuration/WebClientConfiguration.java index 52b3573411..709812db98 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/configuration/WebClientConfiguration.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/configuration/WebClientConfiguration.java @@ -1,5 +1,6 @@ package com.baeldung.requesttimeout.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -11,10 +12,13 @@ import java.time.Duration; @Configuration public class WebClientConfiguration { + @Value("${server.port}") + private int serverPort; + @Bean public WebClient webClient() { return WebClient.builder() - .baseUrl("http://localhost:8080") + .baseUrl("http://localhost:" + serverPort) .clientConnector(new ReactorClientHttpConnector(HttpClient.create().responseTimeout(Duration.ofMillis(250)))) .build(); } diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/BookRepository.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/BookRepository.java index 8ecab0f1d2..5eb4bc7268 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/BookRepository.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/BookRepository.java @@ -1,14 +1,21 @@ package com.baeldung.requesttimeout.domain; +import com.google.common.base.Stopwatch; import org.springframework.data.jpa.repository.JpaRepository; +import static java.util.concurrent.TimeUnit.SECONDS; + public interface BookRepository extends JpaRepository { - default int wasteTime() { - int i = Integer.MIN_VALUE; - while(i < Integer.MAX_VALUE) { - i++; + default void wasteTime() { + Stopwatch watch = Stopwatch.createStarted(); + + // delay for 2 seconds + while (watch.elapsed(SECONDS) < 2) { + int i = Integer.MIN_VALUE; + while (i < Integer.MAX_VALUE) { + i++; + } } - return i; } } diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java index 8a9a921036..e3c0237b06 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java @@ -12,9 +12,9 @@ import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; -@Profile("!prod") +@Profile("!prod && swagger") +//@Profile("!prod") // @Profile("swagger") -// @Profile("!prod && swagger") // @ConditionalOnExpression(value = "${useSwagger:false}") @Configuration @EnableSwagger2 diff --git a/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/longpolling/BakeryControllerIntegrationTest.java similarity index 98% rename from spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java rename to spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/longpolling/BakeryControllerIntegrationTest.java index abc40d72ca..99a5172c52 100644 --- a/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java +++ b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/longpolling/BakeryControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.longpolling.integration; +package com.baeldung.longpolling; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/requesttimeout/RequestTimeoutUnitTest.java b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java similarity index 52% rename from spring-web-modules/spring-rest-http-2/src/test/com/baeldung/requesttimeout/RequestTimeoutUnitTest.java rename to spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java index da7d40d53c..d30dc351fa 100644 --- a/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/requesttimeout/RequestTimeoutUnitTest.java +++ b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java @@ -1,46 +1,60 @@ package com.baeldung.requesttimeout; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; -@SpringBootTest +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @RunWith(SpringRunner.class) -public class RequestTimeoutTests { +public class RequestTimeoutIntegrationTest { - private static final WebClient WEB_CLIENT = WebClient.builder().baseUrl("http://localhost:8080").build(); + @LocalServerPort + private int port; - @Test(expected = WebClientRequestException.class) + private WebClient webClient; + + @Before + public void setUp() { + webClient = WebClient.builder() + .baseUrl("http://localhost:" + port) + .build(); + } + + @Test(expected = WebClientResponseException.InternalServerError.class) public void givenTransactionTimeout_whenTimeExpires_thenReceiveException() { getAuthor("transactional"); } - @Test(expected = WebClientRequestException.class) + @Test(expected = WebClientResponseException.InternalServerError.class) public void givenResilience4jTimeLimiter_whenTimeExpires_thenReceiveException() { getAuthor("resilience4j"); } - @Test(expected = WebClientRequestException.class) + @Test(expected = WebClientResponseException.ServiceUnavailable.class) public void givenMvcRequestTimeout_whenTimeExpires_thenReceiveException() { getAuthor("mvc-request-timeout"); } - @Test(expected = WebClientRequestException.class) + @Test(expected = WebClientResponseException.InternalServerError.class) public void givenWebClientTimeout_whenTimeExpires_thenReceiveException() { getAuthor("webclient"); } private void getAuthor(String authorPath) { - WEB_CLIENT.get() + webClient.get() .uri(uriBuilder -> uriBuilder - .path("/author/" + authorPath) - .queryParam("title", "title") - .build()) + .path("/author/" + authorPath) + .queryParam("title", "title") + .build()) .retrieve() .bodyToMono(String.class) .block(); } + } diff --git a/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/uribuilder/SpringUriBuilderUnitTest.java similarity index 74% rename from spring-web-modules/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java rename to spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/uribuilder/SpringUriBuilderUnitTest.java index 0af5cb1e1a..b4f261cd6e 100644 --- a/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java +++ b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/uribuilder/SpringUriBuilderUnitTest.java @@ -1,39 +1,47 @@ package com.baeldung.uribuilder; -import static org.junit.Assert.assertEquals; - -import java.util.Collections; - import org.junit.Test; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -public class SpringUriBuilderIntegrationTest { +import java.util.Collections; + +import static org.junit.Assert.assertEquals; + +public class SpringUriBuilderUnitTest { @Test public void constructUri() { - UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("www.baeldung.com").path("/junit-5").build(); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("www.baeldung.com").path("/junit-5") + .build(); assertEquals("http://www.baeldung.com/junit-5", uriComponents.toUriString()); } @Test public void constructUriEncoded() { - UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("www.baeldung.com").path("/junit 5").build().encode(); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("www.baeldung.com").path("/junit 5") + .build().encode(); assertEquals("http://www.baeldung.com/junit%205", uriComponents.toUriString()); } @Test public void constructUriFromTemplate() { - UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("www.baeldung.com").path("/{article-name}").buildAndExpand("junit-5"); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("www.baeldung.com").path("/{article-name}") + .buildAndExpand("junit-5"); assertEquals("http://www.baeldung.com/junit-5", uriComponents.toUriString()); } @Test public void constructUriWithQueryParameter() { - UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("www.google.com").path("/").query("q={keyword}").buildAndExpand("baeldung"); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("www.google.com").path("/").query("q={keyword}") + .buildAndExpand("baeldung"); assertEquals("http://www.google.com/?q=baeldung", uriComponents.toUriString()); } diff --git a/spring-web-modules/spring-rest-http/README.md b/spring-web-modules/spring-rest-http/README.md index 2271858f0a..43355d27cd 100644 --- a/spring-web-modules/spring-rest-http/README.md +++ b/spring-web-modules/spring-rest-http/README.md @@ -1,13 +1,12 @@ ## Spring REST HTTP -This module contains articles about HTTP in REST APIs with Spring +This module contains articles about HTTP in REST APIs with Spring. ### The Course The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Guide to UriComponentsBuilder in Spring](https://www.baeldung.com/spring-uricomponentsbuilder) - [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header) - The tests contained for this article rely on the sample application within the [spring-resttemplate](/spring-resttemplate) module - [Returning Custom Status Codes from Spring Controllers](https://www.baeldung.com/spring-mvc-controller-custom-http-status-code) - [Spring RequestMapping](https://www.baeldung.com/spring-requestmapping) @@ -15,3 +14,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using JSON Patch in Spring REST APIs](https://www.baeldung.com/spring-rest-json-patch) - [OpenAPI JSON Objects as Query Parameters](https://www.baeldung.com/openapi-json-query-parameters) - [Dates in OpenAPI Files](https://www.baeldung.com/openapi-dates) +- More articles: [[next -->]](../spring-rest-http-2) diff --git a/spring-web-modules/spring-rest-http/src/test/resources/logback-test.xml b/spring-web-modules/spring-rest-http/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-rest-http/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-rest-query-language/pom.xml b/spring-web-modules/spring-rest-query-language/pom.xml index c5a8c172f3..987d678439 100644 --- a/spring-web-modules/spring-rest-query-language/pom.xml +++ b/spring-web-modules/spring-rest-query-language/pom.xml @@ -181,16 +181,6 @@ spring-test test - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - @@ -312,8 +302,6 @@ 1.4.9 3.21.0-GA 1.4.01 - - 19.0 1.7.0 1.1.3 diff --git a/spring-web-modules/spring-rest-shell/pom.xml b/spring-web-modules/spring-rest-shell/pom.xml index b83a0b6002..992092f43f 100644 --- a/spring-web-modules/spring-rest-shell/pom.xml +++ b/spring-web-modules/spring-rest-shell/pom.xml @@ -37,13 +37,4 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-web-modules/spring-rest-simple/pom.xml b/spring-web-modules/spring-rest-simple/pom.xml index 46bfa5d04c..2764ac8393 100644 --- a/spring-web-modules/spring-rest-simple/pom.xml +++ b/spring-web-modules/spring-rest-simple/pom.xml @@ -119,22 +119,6 @@ okhttp ${com.squareup.okhttp3.version} - - - org.junit.vintage - junit-vintage-engine - test - - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - org.springframework spring-test @@ -303,8 +287,6 @@ 1.4 3.1.0 1.4.9 - - 20.0 2.9.0 1.6.0 diff --git a/spring-web-modules/spring-rest-testing/README.md b/spring-web-modules/spring-rest-testing/README.md index 2a77b5dded..806e67b7ec 100644 --- a/spring-web-modules/spring-rest-testing/README.md +++ b/spring-web-modules/spring-rest-testing/README.md @@ -11,7 +11,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Integration Testing with the Maven Cargo plugin](https://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin) -- [Metrics for your Spring REST API](https://www.baeldung.com/spring-rest-api-metrics) - [Testing Exceptions with Spring MockMvc](https://www.baeldung.com/spring-mvc-test-exceptions) ### Build the Project diff --git a/spring-web-modules/spring-rest-testing/pom.xml b/spring-web-modules/spring-rest-testing/pom.xml index dc5fdcd323..67b3115a6f 100644 --- a/spring-web-modules/spring-rest-testing/pom.xml +++ b/spring-web-modules/spring-rest-testing/pom.xml @@ -21,19 +21,10 @@ org.springframework.boot spring-boot-starter-web - - org.springframework.boot - spring-boot-starter-actuator - org.aspectj aspectjweaver - - org.apache.tomcat.embed - tomcat-embed-jasper - provided - org.springframework @@ -69,23 +60,10 @@ org.springframework spring-expression - - org.springframework - spring-web - - - org.springframework - spring-webmvc - org.springframework.data spring-data-commons - - - org.springframework.boot - spring-boot-starter-tomcat - org.apache.httpcomponents @@ -137,17 +115,6 @@ net.bytebuddy byte-buddy - - - javax.servlet - javax.servlet-api - provided - - - javax.servlet - jstl - runtime - com.fasterxml.jackson.core @@ -165,16 +132,6 @@ spring-test test - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - @@ -192,17 +149,9 @@ org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} + cargo-maven3-plugin + ${cargo-maven3-plugin.version} - true - - jetty8x - embedded - - - - 8082 @@ -232,15 +181,32 @@ - live + cargo-integration + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + none + + + **/*LiveTest.java + + + + + org.codehaus.cargo - cargo-maven2-plugin - - false - + cargo-maven3-plugin start-server @@ -268,10 +234,9 @@ 1.4.9 1.4.01 - 19.0 3.25.0-GA - 1.6.1 + 1.9.9 1.1.3 diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java index c35c4d7e5e..78c9b88ddb 100644 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java @@ -1,38 +1,19 @@ package com.baeldung.spring; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.web.context.request.RequestContextListener; /** * Main Application Class - uses Spring Boot. Just run this as a normal Java * class to run up a Jetty Server (on http://localhost:8082/spring-rest-full) * */ -@EnableScheduling @EnableAutoConfiguration @ComponentScan("com.baeldung") @SpringBootApplication -public class Application extends SpringBootServletInitializer { - - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(Application.class); - } - - @Override - public void onStartup(ServletContext sc) throws ServletException { - // Manages the lifecycle of the root application context - sc.addListener(new RequestContextListener()); - } +public class Application { public static void main(final String[] args) { SpringApplication.run(Application.class, args); diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java deleted file mode 100644 index 005f6f023b..0000000000 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.web.controller; - -import java.util.Map; - -import com.baeldung.web.metric.IActuatorMetricService; -import com.baeldung.web.metric.IMetricService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -@RequestMapping(value = "/auth/") -public class RootController { - - @Autowired - private IMetricService metricService; - - @Autowired - private IActuatorMetricService actMetricService; - - public RootController() { - super(); - } - - // API - - @RequestMapping(value = "/metric", method = RequestMethod.GET) - @ResponseBody - public Map getMetric() { - return metricService.getFullMetric(); - } - - @RequestMapping(value = "/status-metric", method = RequestMethod.GET) - @ResponseBody - public Map getStatusMetric() { - return metricService.getStatusMetric(); - } - - @RequestMapping(value = "/metric-graph", method = RequestMethod.GET) - @ResponseBody - public Object[][] drawMetric() { - final Object[][] result = metricService.getGraphData(); - for (int i = 1; i < result[0].length; i++) { - result[0][i] = result[0][i].toString(); - } - return result; - } - - -} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java deleted file mode 100644 index 60bb43ee00..0000000000 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.web.metric; - -public interface IActuatorMetricService { - Object[][] getGraphData(); -} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java deleted file mode 100644 index 5126252e27..0000000000 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.web.metric; - -public interface ICustomActuatorMetricService { - - void increaseCount(final int status); - - Object[][] getGraphData(); -} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java deleted file mode 100644 index b8dfa60215..0000000000 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.web.metric; - -import java.util.Map; - -public interface IMetricService { - - void increaseCount(final String request, final int status); - - Map getFullMetric(); - - Map getStatusMetric(); - - Object[][] getGraphData(); -} diff --git a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java deleted file mode 100644 index fd3cccab3e..0000000000 --- a/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.baeldung.web.metric; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.springframework.stereotype.Service; - -@Service -public class MetricService implements IMetricService { - - private ConcurrentMap> metricMap; - private ConcurrentMap statusMetric; - private ConcurrentMap> timeMap; - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - - public MetricService() { - super(); - metricMap = new ConcurrentHashMap>(); - statusMetric = new ConcurrentHashMap(); - timeMap = new ConcurrentHashMap>(); - } - - // API - - @Override - public void increaseCount(final String request, final int status) { - increaseMainMetric(request, status); - increaseStatusMetric(status); - updateTimeMap(status); - } - - @Override - public Map getFullMetric() { - return metricMap; - } - - @Override - public Map getStatusMetric() { - return statusMetric; - } - - @Override - public Object[][] getGraphData() { - final int colCount = statusMetric.keySet().size() + 1; - final Set allStatus = statusMetric.keySet(); - final int rowCount = timeMap.keySet().size() + 1; - - final Object[][] result = new Object[rowCount][colCount]; - result[0][0] = "Time"; - - int j = 1; - for (final int status : allStatus) { - result[0][j] = status; - j++; - } - int i = 1; - ConcurrentMap tempMap; - for (final Entry> entry : timeMap.entrySet()) { - result[i][0] = entry.getKey(); - tempMap = entry.getValue(); - for (j = 1; j < colCount; j++) { - result[i][j] = tempMap.get(result[0][j]); - if (result[i][j] == null) { - result[i][j] = 0; - } - } - i++; - } - - return result; - } - - // NON-API - - private void increaseMainMetric(final String request, final int status) { - ConcurrentHashMap statusMap = metricMap.get(request); - if (statusMap == null) { - statusMap = new ConcurrentHashMap(); - } - - Integer count = statusMap.get(status); - if (count == null) { - count = 1; - } else { - count++; - } - statusMap.put(status, count); - metricMap.put(request, statusMap); - } - - private void increaseStatusMetric(final int status) { - final Integer statusCount = statusMetric.get(status); - if (statusCount == null) { - statusMetric.put(status, 1); - } else { - statusMetric.put(status, statusCount + 1); - } - } - - private void updateTimeMap(final int status) { - final String time = dateFormat.format(new Date()); - ConcurrentHashMap statusMap = timeMap.get(time); - if (statusMap == null) { - statusMap = new ConcurrentHashMap(); - } - - Integer count = statusMap.get(status); - if (count == null) { - count = 1; - } else { - count++; - } - statusMap.put(status, count); - timeMap.put(time, statusMap); - } - -} diff --git a/spring-web-modules/spring-rest-testing/src/main/resources/application.properties b/spring-web-modules/spring-rest-testing/src/main/resources/application.properties index 52d93b4cff..cb9d72e41f 100644 --- a/spring-web-modules/spring-rest-testing/src/main/resources/application.properties +++ b/spring-web-modules/spring-rest-testing/src/main/resources/application.properties @@ -1,3 +1,2 @@ server.port=8082 server.servlet.context-path=/spring-rest-full -endpoints.metrics.enabled=true \ No newline at end of file diff --git a/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/cargo/CargoPluginLiveTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/cargo/CargoPluginLiveTest.java new file mode 100644 index 0000000000..8d6dd6a823 --- /dev/null +++ b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/cargo/CargoPluginLiveTest.java @@ -0,0 +1,13 @@ +package com.baeldung.cargo; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CargoPluginLiveTest { + + @Test + void givenCargoProfile_expectTestRuns() { + assertTrue(true); + } +} diff --git a/spring-web-modules/spring-resttemplate-2/pom.xml b/spring-web-modules/spring-resttemplate-2/pom.xml index d0191b970e..b87b245da9 100644 --- a/spring-web-modules/spring-resttemplate-2/pom.xml +++ b/spring-web-modules/spring-resttemplate-2/pom.xml @@ -66,13 +66,4 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-2/src/test/resources/logback-test.xml b/spring-web-modules/spring-resttemplate-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/pom.xml b/spring-web-modules/spring-resttemplate-3/pom.xml index 8e313ccf39..b036a5ffcb 100644 --- a/spring-web-modules/spring-resttemplate-3/pom.xml +++ b/spring-web-modules/spring-resttemplate-3/pom.xml @@ -16,7 +16,6 @@ - org.springframework.boot spring-boot-starter-web diff --git a/spring-web-modules/spring-resttemplate/pom.xml b/spring-web-modules/spring-resttemplate/pom.xml index 1379e40d23..4ad2f9dc58 100644 --- a/spring-web-modules/spring-resttemplate/pom.xml +++ b/spring-web-modules/spring-resttemplate/pom.xml @@ -108,21 +108,6 @@ ${com.squareup.okhttp3.version} - - - org.junit.vintage - junit-vintage-engine - - - org.hamcrest - hamcrest - test - - - org.mockito - mockito-core - test - org.springframework spring-test @@ -273,8 +258,6 @@ 1.4.9 - - 20.0 1.6.1 3.0.4 diff --git a/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java index 9a992f390a..6e2072efe3 100644 --- a/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java @@ -9,7 +9,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; diff --git a/spring-web-modules/spring-thymeleaf-2/README.md b/spring-web-modules/spring-thymeleaf-2/README.md index a8c067a443..488a0bdc2d 100644 --- a/spring-web-modules/spring-thymeleaf-2/README.md +++ b/spring-web-modules/spring-thymeleaf-2/README.md @@ -5,13 +5,10 @@ This module contains articles about Spring with Thymeleaf ## Relevant Articles: - [Working with Enums in Thymeleaf](https://www.baeldung.com/thymeleaf-enums) -- [Changing the Thymeleaf Template Directory in Spring Boot](https://www.baeldung.com/spring-thymeleaf-template-directory) - [Spring Request Parameters with Thymeleaf](https://www.baeldung.com/spring-thymeleaf-request-parameters) - [Thymeleaf lists Utility Object](https://www.baeldung.com/thymeleaf-lists-utility) - [Spring Path Variables with Thymeleaf](https://www.baeldung.com/spring-thymeleaf-path-variables) - [Working with Arrays in Thymeleaf](https://www.baeldung.com/thymeleaf-arrays) - [Working with Boolean in Thymeleaf](https://www.baeldung.com/thymeleaf-boolean) - [Working With Custom HTML Attributes in Thymeleaf](https://www.baeldung.com/thymeleaf-custom-html-attributes) -- [How to Create an Executable JAR with Maven](https://www.baeldung.com/executable-jar-with-maven) -- [Spring MVC Data and Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-data) - [[<-- prev]](/spring-thymeleaf) diff --git a/spring-web-modules/spring-thymeleaf-2/pom.xml b/spring-web-modules/spring-thymeleaf-2/pom.xml index b2b893ecd5..14e4de668b 100644 --- a/spring-web-modules/spring-thymeleaf-2/pom.xml +++ b/spring-web-modules/spring-thymeleaf-2/pom.xml @@ -65,8 +65,6 @@ - 1.8 - 1.8 2.2 diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/participants.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/participants.html deleted file mode 100644 index f7e017e777..0000000000 --- a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/participants.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - -

Enter participant

-
- - - - - -
- - -

User Details

-

Details for user [[${id}]] ...

-
- -

Users

- -

- User [[${userId}]] -

-
- - diff --git a/spring-web-modules/spring-thymeleaf-2/src/test/resources/logback-test.xml b/spring-web-modules/spring-thymeleaf-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-3/README.md b/spring-web-modules/spring-thymeleaf-3/README.md index 76c54d3885..46ddd6c03f 100644 --- a/spring-web-modules/spring-thymeleaf-3/README.md +++ b/spring-web-modules/spring-thymeleaf-3/README.md @@ -11,3 +11,4 @@ This module contains articles about Spring with Thymeleaf - [Using Hidden Inputs with Spring and Thymeleaf](https://www.baeldung.com/spring-thymeleaf-hidden-inputs) - [Thymeleaf Variables](https://www.baeldung.com/thymeleaf-variables) - [Displaying Error Messages with Thymeleaf in Spring](https://www.baeldung.com/spring-thymeleaf-error-messages) +- [[next -->]](/spring-thymeleaf-4) diff --git a/spring-web-modules/spring-thymeleaf-4/README.md b/spring-web-modules/spring-thymeleaf-4/README.md new file mode 100644 index 0000000000..f8dc4c8b4e --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/README.md @@ -0,0 +1,27 @@ +## Spring Thymeleaf + +This module contains articles about Spring with Thymeleaf + +### Relevant Articles: +- [CSRF Protection with Spring MVC and Thymeleaf](https://www.baeldung.com/csrf-thymeleaf-with-spring-security) +- [Conditionals in Thymeleaf](https://www.baeldung.com/spring-thymeleaf-conditionals) +- [Iteration in Thymeleaf](https://www.baeldung.com/thymeleaf-iteration) +- [Spring with Thymeleaf Pagination for a List](https://www.baeldung.com/spring-thymeleaf-pagination) + +### Build the Project + +mvn clean install + +### Run the Project + +mvn cargo:run +- **note**: starts on port '8082' + +Access the pages using the URLs: + + - http://localhost:8082/spring-thymeleaf-4/ + - http://localhost:8082/spring-thymeleaf-4/addStudent/ + - http://localhost:8082/spring-thymeleaf-4/listStudents/ + +The first URL is the home page of the application. The home page has links to the second and third pages. + diff --git a/spring-web-modules/spring-thymeleaf-4/pom.xml b/spring-web-modules/spring-thymeleaf-4/pom.xml new file mode 100644 index 0000000000..8063b14c39 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/pom.xml @@ -0,0 +1,148 @@ + + + 4.0.0 + spring-thymeleaf-4 + spring-thymeleaf-4 + war + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../../parent-spring-5 + + + + + + org.springframework + spring-context + ${spring.version} + + + + commons-logging + commons-logging + + + + + org.springframework + spring-webmvc + ${spring.version} + + + org.springframework.data + spring-data-commons + ${spring-data.version} + + + javax.validation + validation-api + ${javax.validation-version} + + + org.hibernate.validator + hibernate-validator + ${hibernate-validator.version} + + + + org.springframework.security + spring-security-web + ${spring-security.version} + + + org.springframework.security + spring-security-config + ${spring-security.version} + + + + org.thymeleaf + thymeleaf + ${org.thymeleaf-version} + + + org.thymeleaf + thymeleaf-spring5 + ${org.thymeleaf-version} + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + ${thymeleaf-layout-dialect.version} + + + org.thymeleaf.extras + thymeleaf-extras-java8time + ${org.thymeleaf.extras-version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework.security + spring-security-test + ${spring-security.version} + test + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty9x + embedded + + + + + + 8082 + + + + + + + + + 2.3.2.RELEASE + 3.0.11.RELEASE + 3.0.4.RELEASE + 2.4.1 + 2.0.1.Final + 6.0.11.Final + + 1.6.1 + + + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java new file mode 100644 index 0000000000..956db4a0e5 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java @@ -0,0 +1,11 @@ +package com.baeldung.thymeleaf.config; + +import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; + +public class InitSecurity extends AbstractSecurityWebApplicationInitializer { + + public InitSecurity() { + super(WebMVCSecurity.class); + + } +} diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebApp.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebApp.java new file mode 100644 index 0000000000..0913152bc3 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebApp.java @@ -0,0 +1,36 @@ +package com.baeldung.thymeleaf.config; + +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + +import javax.servlet.ServletRegistration.Dynamic; + +/** + * Java configuration file that is used for web application initialization + */ +public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer { + + public WebApp() { + super(); + } + + @Override + protected Class[] getRootConfigClasses() { + return null; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[] { WebMVCConfig.class }; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + + @Override + protected void customizeRegistration(final Dynamic registration) { + super.customizeRegistration(registration); + } + +} diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java new file mode 100644 index 0000000000..50a555a017 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java @@ -0,0 +1,115 @@ +package com.baeldung.thymeleaf.config; + +import com.baeldung.thymeleaf.formatter.NameFormatter; +import com.baeldung.thymeleaf.utils.ArrayUtil; +import nz.net.ultraq.thymeleaf.LayoutDialect; +import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; +import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect; +import org.thymeleaf.spring5.ISpringTemplateEngine; +import org.thymeleaf.spring5.SpringTemplateEngine; +import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.spring5.view.ThymeleafViewResolver; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ITemplateResolver; + +import java.util.Locale; + +@Configuration +@EnableWebMvc +@ComponentScan({ "com.baeldung.thymeleaf" }) +/* + Java configuration file that is used for Spring MVC and Thymeleaf + configurations + */ +public class WebMVCConfig implements WebMvcConfigurer, ApplicationContextAware { + + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Bean + public ViewResolver htmlViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(htmlTemplateResolver())); + resolver.setContentType("text/html"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.html")); + return resolver; + } + + private ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.addDialect(new LayoutDialect(new GroupingStrategy())); + engine.addDialect(new Java8TimeDialect()); + engine.setTemplateResolver(templateResolver); + engine.setTemplateEngineMessageSource(messageSource()); + return engine; + } + + private ITemplateResolver htmlTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/views/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.HTML); + return resolver; + } + + @Bean + @Description("Spring Message Resolver") + public ResourceBundleMessageSource messageSource() { + ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("messages"); + return messageSource; + } + + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver localeResolver = new SessionLocaleResolver(); + localeResolver.setDefaultLocale(new Locale("en")); + return localeResolver; + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("lang"); + return localeChangeInterceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**", "/css/**") + .addResourceLocations("/WEB-INF/resources/", "/WEB-INF/css/"); + } + + @Override + @Description("Custom Conversion Service") + public void addFormatters(FormatterRegistry registry) { + registry.addFormatter(new NameFormatter()); + } +} diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java new file mode 100644 index 0000000000..ea51ca3cd9 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java @@ -0,0 +1,43 @@ +package com.baeldung.thymeleaf.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) +public class WebMVCSecurity extends WebSecurityConfigurerAdapter { + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + public WebMVCSecurity() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("user1").password("{noop}user1Pass").authorities("ROLE_USER"); + } + + @Override + public void configure(final WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); + } + +} diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/BookController.java similarity index 99% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/BookController.java index d10caee9e7..194bf5825f 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/BookController.java @@ -1,22 +1,20 @@ package com.baeldung.thymeleaf.controller; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - +import com.baeldung.thymeleaf.model.Book; +import com.baeldung.thymeleaf.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; - import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import com.baeldung.thymeleaf.model.Book; -import com.baeldung.thymeleaf.service.BookService; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; @Controller public class BookController { diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java index 21f230c84c..8bbcd8fdb7 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java @@ -1,14 +1,14 @@ package com.baeldung.thymeleaf.controller; -import java.text.DateFormat; -import java.util.Date; -import java.util.Locale; - import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + /** * Handles requests for the application home page. * diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java similarity index 99% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java index 77cf02c902..99dd5501ae 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java @@ -1,9 +1,7 @@ package com.baeldung.thymeleaf.controller; -import java.util.List; - -import javax.validation.Valid; - +import com.baeldung.thymeleaf.model.Student; +import com.baeldung.thymeleaf.utils.StudentUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -11,8 +9,8 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import com.baeldung.thymeleaf.model.Student; -import com.baeldung.thymeleaf.utils.StudentUtils; +import javax.validation.Valid; +import java.util.List; /** * Handles requests for the student model. diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java similarity index 99% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java index 844d746084..c3a106f11a 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java @@ -1,12 +1,11 @@ package com.baeldung.thymeleaf.controller; +import com.baeldung.thymeleaf.utils.TeacherUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import com.baeldung.thymeleaf.utils.TeacherUtils; - @Controller public class TeacherController { diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java new file mode 100644 index 0000000000..5fd5e88651 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java @@ -0,0 +1,30 @@ +package com.baeldung.thymeleaf.formatter; + +import org.springframework.format.Formatter; +import org.thymeleaf.util.StringUtils; + +import java.text.ParseException; +import java.util.Locale; + +/** + * + * Name formatter class that implements the Spring Formatter interface. + * Formats a name(String) and return the value with spaces replaced by commas. + * + */ +public class NameFormatter implements Formatter { + + @Override + public String print(String input, Locale locale) { + return formatName(input, locale); + } + + @Override + public String parse(String input, Locale locale) throws ParseException { + return formatName(input, locale); + } + + private String formatName(String input, Locale locale) { + return StringUtils.replace(input, " ", ","); + } +} diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Book.java similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Book.java diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Student.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Student.java new file mode 100644 index 0000000000..ca76cec986 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Student.java @@ -0,0 +1,59 @@ +package com.baeldung.thymeleaf.model; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * + * Simple student POJO with few fields + * + */ +public class Student implements Serializable { + + private static final long serialVersionUID = -8582553475226281591L; + + @NotNull(message = "Student ID is required.") + @Min(value = 1000, message = "Student ID must be at least 4 digits.") + private Integer id; + + @NotNull(message = "Student name is required.") + private String name; + + @NotNull(message = "Student gender is required.") + private Character gender; + + private Float percentage; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Character getGender() { + return gender; + } + + public void setGender(Character gender) { + this.gender = gender; + } + + public Float getPercentage() { + return percentage; + } + + public void setPercentage(Float percentage) { + this.percentage = percentage; + } +} diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Teacher.java similarity index 99% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Teacher.java index ad43590818..62f8a2938a 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/model/Teacher.java @@ -1,11 +1,10 @@ package com.baeldung.thymeleaf.model; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; public class Teacher implements Serializable { diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/service/BookService.java similarity index 99% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/service/BookService.java index 2aaa559251..a330a924bd 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/service/BookService.java @@ -1,16 +1,15 @@ package com.baeldung.thymeleaf.service; -import java.util.Collections; -import java.util.List; - +import com.baeldung.thymeleaf.model.Book; +import com.baeldung.thymeleaf.utils.BookUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import com.baeldung.thymeleaf.model.Book; -import com.baeldung.thymeleaf.utils.BookUtils; +import java.util.Collections; +import java.util.List; @Service public class BookService { diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java new file mode 100644 index 0000000000..5c07476c9b --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java @@ -0,0 +1,8 @@ +package com.baeldung.thymeleaf.utils; + +public class ArrayUtil { + + public static String[] array(String... args) { + return args; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java index 3cd9e6a92e..0a23a1bdba 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java @@ -1,11 +1,11 @@ package com.baeldung.thymeleaf.utils; +import com.baeldung.thymeleaf.model.Book; + import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; -import com.baeldung.thymeleaf.model.Book; - public class BookUtils { private static List books = new ArrayList(); diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java new file mode 100644 index 0000000000..0e1165333d --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java @@ -0,0 +1,34 @@ +package com.baeldung.thymeleaf.utils; + +import com.baeldung.thymeleaf.model.Student; + +import java.util.ArrayList; +import java.util.List; + +public class StudentUtils { + + private static List students = new ArrayList(); + + public static List buildStudents() { + if (students.isEmpty()) { + Student student1 = new Student(); + student1.setId(1001); + student1.setName("John Smith"); + student1.setGender('M'); + student1.setPercentage(Float.valueOf("80.45")); + + students.add(student1); + + Student student2 = new Student(); + student2.setId(1002); + student2.setName("Jane Williams"); + student2.setGender('F'); + student2.setPercentage(Float.valueOf("60.25")); + + students.add(student2); + } + + return students; + } + +} diff --git a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java rename to spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java index 1bb279cc92..f4b759e9df 100644 --- a/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java @@ -1,10 +1,10 @@ package com.baeldung.thymeleaf.utils; +import com.baeldung.thymeleaf.model.Teacher; + import java.util.ArrayList; import java.util.List; -import com.baeldung.thymeleaf.model.Teacher; - public class TeacherUtils { private static List teachers = new ArrayList(); diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/logback.xml b/spring-web-modules/spring-thymeleaf-4/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/messages_en.properties b/spring-web-modules/spring-thymeleaf-4/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..b534d448b6 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/main/resources/messages_en.properties @@ -0,0 +1,13 @@ +msg.id=ID +msg.name=Name +msg.gender=Gender +msg.percent=Percentage +welcome.message=Welcome Student !!! +msg.AddStudent=Add Student +msg.ListStudents=List Students +msg.Home=Home +msg.ListTeachers=List Teachers +msg.ListBooks=List Books with paging +msg.courses=Courses +msg.skills=Skills +msg.active=Active \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/addStudent.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/addStudent.html diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/csrfAttack.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/csrfAttack.html diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/home.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/home.html diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listBooks.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listBooks.html diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listStudents.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listStudents.html diff --git a/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html b/spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listTeachers.html similarity index 100% rename from spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html rename to spring-web-modules/spring-thymeleaf-4/src/main/webapp/WEB-INF/views/listTeachers.html diff --git a/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java new file mode 100644 index 0000000000..e2708330f2 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java @@ -0,0 +1,19 @@ +package com.baeldung.thymeleaf; + +import com.baeldung.thymeleaf.config.WebApp; +import com.baeldung.thymeleaf.config.WebMVCConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class }) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/controller/ControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/controller/ControllerIntegrationTest.java new file mode 100644 index 0000000000..cbbcdc0868 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/controller/ControllerIntegrationTest.java @@ -0,0 +1,63 @@ +package com.baeldung.thymeleaf.controller; + +import com.baeldung.thymeleaf.config.WebApp; +import com.baeldung.thymeleaf.config.WebMVCConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import javax.servlet.Filter; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class}) +public class ControllerIntegrationTest { + + @Autowired + WebApplicationContext wac; + + private MockMvc mockMvc; + + @Autowired + private Filter springSecurityFilterChain; + + private RequestPostProcessor testUser() { + return user("user1").password("user1Pass").roles("USER"); + } + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); + } + + @Test + public void testTeachers() throws Exception { + mockMvc.perform(get("/listTeachers").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("listTeachers.html")); + } + + @Test + public void addStudentWithoutCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void addStudentWithCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser()).with(csrf())).andExpect(status().isOk()); + } +} diff --git a/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java new file mode 100644 index 0000000000..08a31cfa83 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java @@ -0,0 +1,62 @@ +package com.baeldung.thymeleaf.security.csrf; + +import com.baeldung.thymeleaf.config.InitSecurity; +import com.baeldung.thymeleaf.config.WebApp; +import com.baeldung.thymeleaf.config.WebMVCConfig; +import com.baeldung.thymeleaf.config.WebMVCSecurity; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import javax.servlet.Filter; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) +public class CsrfEnabledIntegrationTest { + + @Autowired + WebApplicationContext wac; + @Autowired + MockHttpSession session; + + private MockMvc mockMvc; + + @Autowired + private Filter springSecurityFilterChain; + + private RequestPostProcessor testUser() { + return user("user1").password("user1Pass").roles("USER"); + } + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); + } + + @Test + public void addStudentWithoutCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void addStudentWithCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser()).with(csrf())).andExpect(status().isOk()); + } + +} diff --git a/spring-web-modules/spring-thymeleaf-5/README.md b/spring-web-modules/spring-thymeleaf-5/README.md new file mode 100644 index 0000000000..7bbaa8b4db --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/README.md @@ -0,0 +1,10 @@ +## Spring Thymeleaf + +This module contains articles about Spring with Thymeleaf + +## Relevant Articles: + +- [Changing the Thymeleaf Template Directory in Spring Boot](https://www.baeldung.com/spring-thymeleaf-template-directory) +- [How to Create an Executable JAR with Maven](https://www.baeldung.com/executable-jar-with-maven) +- [Spring MVC Data and Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-data) +- [[<-- prev]](/spring-thymeleaf) diff --git a/spring-web-modules/spring-thymeleaf-5/pom.xml b/spring-web-modules/spring-thymeleaf-5/pom.xml new file mode 100644 index 0000000000..e7c54d83c9 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + spring-thymeleaf-5 + spring-thymeleaf-5 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-test + test + + + + + spring-thymeleaf-5 + + + + 2.2 + + + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/Application.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/Application.java new file mode 100644 index 0000000000..2ccca82497 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/Application.java @@ -0,0 +1,11 @@ +package com.baeldung.thymeleaf; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java rename to spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java rename to spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java rename to spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java rename to spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java rename to spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java diff --git a/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties b/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties new file mode 100644 index 0000000000..b09232bb1b --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties @@ -0,0 +1 @@ +#spring.thymeleaf.prefix=classpath:/templates-2/ \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/hello.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates-2/hello.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/hello.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates-2/hello.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-bean-data.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-bean-data.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-model-attributes.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-model-attributes.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-request-parameters.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-request-parameters.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-servlet-context.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-servlet-context.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-session-attributes.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html rename to spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/mvcdata/email-session-attributes.html diff --git a/spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java b/spring-web-modules/spring-thymeleaf-5/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java similarity index 100% rename from spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java rename to spring-web-modules/spring-thymeleaf-5/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java diff --git a/spring-web-modules/spring-thymeleaf-5/src/test/resources/logback-test.xml b/spring-web-modules/spring-thymeleaf-5/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf/README.md b/spring-web-modules/spring-thymeleaf/README.md index 7c3d4cafa3..12eb97b4a2 100644 --- a/spring-web-modules/spring-thymeleaf/README.md +++ b/spring-web-modules/spring-thymeleaf/README.md @@ -4,15 +4,11 @@ This module contains articles about Spring with Thymeleaf ### Relevant Articles: - [Introduction to Using Thymeleaf in Spring](https://www.baeldung.com/thymeleaf-in-spring-mvc) -- [CSRF Protection with Spring MVC and Thymeleaf](https://www.baeldung.com/csrf-thymeleaf-with-spring-security) - [Thymeleaf: Custom Layout Dialect](https://www.baeldung.com/thymeleaf-spring-layouts) - [Spring and Thymeleaf 3: Expressions](https://www.baeldung.com/spring-thymeleaf-3-expressions) - [Spring MVC + Thymeleaf 3.0: New Features](https://www.baeldung.com/spring-thymeleaf-3) - [How to Work with Dates in Thymeleaf](https://www.baeldung.com/dates-in-thymeleaf) - [Working with Fragments in Thymeleaf](https://www.baeldung.com/spring-thymeleaf-fragments) -- [Conditionals in Thymeleaf](https://www.baeldung.com/spring-thymeleaf-conditionals) -- [Iteration in Thymeleaf](https://www.baeldung.com/thymeleaf-iteration) -- [Spring with Thymeleaf Pagination for a List](https://www.baeldung.com/spring-thymeleaf-pagination) - [[next -->]](/spring-thymeleaf-2) ### Build the Project @@ -24,13 +20,5 @@ mvn clean install mvn cargo:run - **note**: starts on port '8082' -Access the pages using the URLs: - - - http://localhost:8082/spring-thymeleaf/ - - http://localhost:8082/spring-thymeleaf/addStudent/ - - http://localhost:8082/spring-thymeleaf/listStudents/ - -The first URL is the home page of the application. The home page has links to the second and third pages. - ### Security The user/password required is: user1/user1Pass diff --git a/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java index 4a2a9974f1..462e9e8c21 100644 --- a/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java +++ b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java @@ -59,10 +59,5 @@ public class ExpressionUtilityObjectsControllerIntegrationTest { public void testDates() throws Exception { mockMvc.perform(get("/dates").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("dates.html")); } - - @Test - public void testTeachers() throws Exception { - mockMvc.perform(get("/listTeachers").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("listTeachers.html")); - } } diff --git a/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java index a7c9fb4ae4..1160250877 100644 --- a/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java +++ b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java @@ -49,16 +49,6 @@ public class CsrfEnabledIntegrationTest { mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); } - @Test - public void addStudentWithoutCSRF() throws Exception { - mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser())).andExpect(status().isForbidden()); - } - - @Test - public void addStudentWithCSRF() throws Exception { - mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser()).with(csrf())).andExpect(status().isOk()); - } - @Test public void htmlInliningTest() throws Exception { mockMvc.perform(get("/html").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("inliningExample.html")); diff --git a/spring-web-modules/spring-web-url/README.md b/spring-web-modules/spring-web-url/README.md new file mode 100644 index 0000000000..41b479337b --- /dev/null +++ b/spring-web-modules/spring-web-url/README.md @@ -0,0 +1,8 @@ +## Spring Web URL + +This module contains articles about Spring MVC + +## Relevant articles: +- [Using a Slash Character in Spring URLs](https://www.baeldung.com/spring-slash-character-in-url) +- [Excluding URLs for a Filter in a Spring Web Application](https://www.baeldung.com/spring-exclude-filter) +- [Handling URL Encoded Form Data in Spring REST](https://www.baeldung.com/spring-url-encoded-form-data) diff --git a/spring-web-modules/spring-web-url/pom.xml b/spring-web-modules/spring-web-url/pom.xml new file mode 100644 index 0000000000..258ce88afd --- /dev/null +++ b/spring-web-modules/spring-web-url/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + spring-web-url + spring-web-url + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-thymeleaf + provided + + + + + ${project.artifactId} + + + + + com.baeldung.exclude_urls_filter.Application + + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/Application.java similarity index 61% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/Application.java index 4fb6938694..9841a9b967 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java +++ b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/Application.java @@ -2,11 +2,8 @@ package com.baeldung.exclude_urls_filter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -@ComponentScan(basePackages = "com.baeldung.exclude_urls_filter") -@Configuration + @SpringBootApplication public class Application { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/Application.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/Application.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/model/Feedback.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/form_submission/model/Feedback.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/spring/slash/Application.java similarity index 100% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/spring/slash/Application.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/spring/slash/SlashParsingController.java similarity index 95% rename from spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java rename to spring-web-modules/spring-web-url/src/main/java/com/baeldung/spring/slash/SlashParsingController.java index 635587ee5b..07b62a5b4d 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java +++ b/spring-web-modules/spring-web-url/src/main/java/com/baeldung/spring/slash/SlashParsingController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("slash") -public class SlashParsingController { +public class SlashParsingController { @GetMapping("mypaths/{anything}") public String pathVariable(@PathVariable("anything") String anything) { diff --git a/spring-web-modules/spring-web-url/src/main/resources/application.properties b/spring-web-modules/spring-web-url/src/main/resources/application.properties new file mode 100644 index 0000000000..b95b5671b5 --- /dev/null +++ b/spring-web-modules/spring-web-url/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.thymeleaf.cache=false +spring.thymeleaf.enabled=true +spring.thymeleaf.prefix=classpath:/templates/ +spring.thymeleaf.suffix=.html diff --git a/spring-web-modules/spring-web-url/src/main/resources/templates/feedback.html b/spring-web-modules/spring-web-url/src/main/resources/templates/feedback.html new file mode 100644 index 0000000000..4b6a487fc2 --- /dev/null +++ b/spring-web-modules/spring-web-url/src/main/resources/templates/feedback.html @@ -0,0 +1,41 @@ + + + + Poetry Contest: Submission + + + +
+ + + + + + + + + + +
+ + + +
+ + +