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/apache-olingo/olingo2/src/main/resources/logback.xml b/apache-olingo/src/main/resources/logback.xml
similarity index 100%
rename from apache-olingo/olingo2/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/olingo2/src/test/resources/logback-test.xml b/apache-olingo/src/test/resources/logback-test.xml
similarity index 100%
rename from apache-olingo/olingo2/src/test/resources/logback-test.xml
rename to apache-olingo/src/test/resources/logback-test.xml
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-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/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/book b/book
deleted file mode 100644
index e69de29bb2..0000000000
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/resources/logback.xml b/core-java-modules/core-java-collections-3/src/test/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/core-java-modules/core-java-collections-3/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-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-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md
index 1dad941e57..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,7 +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)
- [Set the Name of a Thread in Java](https://www.baeldung.com/java-set-thread-name)
-- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic)
+- [[<-- Prev]](../core-java-concurrency-basic)[[Next -->]](../core-java-concurrency-basic-3)
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/core-java-modules/core-java-concurrency-basic-3/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-basic-3/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-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/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-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/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-io/src/main/resources/log4j.properties b/core-java-modules/core-java-io/src/main/resources/log4j.properties
deleted file mode 100644
index 621cf01735..0000000000
--- a/core-java-modules/core-java-io/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-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-io/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties
deleted file mode 100644
index 5bc2bfe4b9..0000000000
--- a/core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-
-# 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-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/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/pom.xml b/core-java-modules/pom.xml
index 809aa72966..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
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/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 57369c6f52..4131ddeb97 100644
--- a/javaxval/pom.xml
+++ b/javaxval/pom.xml
@@ -15,7 +15,7 @@
- org.hibernate
+ org.hibernate.validator
hibernate-validator
${hibernate-validator.version}
@@ -36,10 +36,45 @@
+
+
+
6.0.13.Final
+ 6.2.0.Final
+ 3.6.1
+ 1.8
+ 1.8
3.0.0
5.0.2.RELEASE
-
\ 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/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 d3c7f8287e..ac7c8620cd 100644
--- a/logging-modules/log4j/pom.xml
+++ b/logging-modules/log4j/pom.xml
@@ -46,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 0b6fa9b902..c3a3f4e0f9 100644
--- a/logging-modules/log4j2/pom.xml
+++ b/logging-modules/log4j2/pom.xml
@@ -111,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/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/pom.xml b/maven-modules/pom.xml
index e09283efb4..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
diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml
index 109bf3b64f..b7f33de237 100644
--- a/parent-boot-2/pom.xml
+++ b/parent-boot-2/pom.xml
@@ -88,7 +88,7 @@
3.3.0
1.0.22.RELEASE
- 2.6.1
+ 2.6.3
1.9.1
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/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/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md
index 34acd60c57..fe30c2999e 100644
--- a/persistence-modules/java-mongodb/README.md
+++ b/persistence-modules/java-mongodb/README.md
@@ -12,3 +12,4 @@ This module contains articles about MongoDB in Java.
- [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations)
- [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/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-jpa-filtering/pom.xml b/persistence-modules/spring-data-jpa-filtering/pom.xml
index 287a3136fd..9c10f4a997 100644
--- a/persistence-modules/spring-data-jpa-filtering/pom.xml
+++ b/persistence-modules/spring-data-jpa-filtering/pom.xml
@@ -67,6 +67,7 @@
com.baeldung.boot.Application
1.10.6
42.2.5
+ 2.6.1
\ 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 0e4efed6e6..ac2bf14635 100644
--- a/persistence-modules/spring-data-mongodb-reactive/pom.xml
+++ b/persistence-modules/spring-data-mongodb-reactive/pom.xml
@@ -124,7 +124,7 @@
- 5.3.13
+ 5.3.15
4.5.2
3.3.1.RELEASE
3.2.6
diff --git a/persistence-modules/spring-mybatis/pom.xml b/persistence-modules/spring-mybatis/pom.xml
index eb0ebd723d..65a8581f97 100644
--- a/persistence-modules/spring-mybatis/pom.xml
+++ b/persistence-modules/spring-mybatis/pom.xml
@@ -78,7 +78,7 @@
- 5.3.13
+ 5.3.15
2.0.6
3.5.2
diff --git a/pom.xml b/pom.xml
index c2979b9ed1..a4cdb35e65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -353,7 +353,7 @@
apache-cxf
apache-kafka
apache-libraries
- apache-olingo/olingo2
+ apache-olingo
apache-poi
apache-rocketmq
apache-shiro
@@ -839,7 +839,7 @@
apache-cxf
apache-kafka
apache-libraries
- apache-olingo/olingo2
+ apache-olingo
apache-poi
apache-rocketmq
apache-shiro
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/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/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/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/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/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/App.java b/spring-5-autowiring-beans/src/main/java/com/baeldung/autowiring/App.java
new file mode 100644
index 0000000000..d2d0db7a60
--- /dev/null
+++ b/spring-5-autowiring-beans/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-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-boot-modules/pom.xml b/spring-boot-modules/pom.xml
index ac0deaa9e5..4925530a35 100644
--- a/spring-boot-modules/pom.xml
+++ b/spring-boot-modules/pom.xml
@@ -52,6 +52,7 @@
spring-boot-libraries
spring-boot-libraries-2
spring-boot-logging-log4j2
+ spring-boot-multiple-datasources
spring-boot-mvc
spring-boot-mvc-2
spring-boot-mvc-3
diff --git a/spring-boot-modules/spring-boot-1/pom.xml b/spring-boot-modules/spring-boot-1/pom.xml
index b6e3717f7c..594e6459a4 100644
--- a/spring-boot-modules/spring-boot-1/pom.xml
+++ b/spring-boot-modules/spring-boot-1/pom.xml
@@ -68,7 +68,7 @@
- 2.14.1
+ 2.17.1
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-2/pom.xml b/spring-boot-modules/spring-boot-2/pom.xml
index 65bacb7c47..08dc517fa0 100644
--- a/spring-boot-modules/spring-boot-2/pom.xml
+++ b/spring-boot-modules/spring-boot-2/pom.xml
@@ -63,7 +63,7 @@
2.14.1
- 5.3.13
+ 5.3.15
11
11
diff --git a/spring-boot-modules/spring-boot-actuator/README.md b/spring-boot-modules/spring-boot-actuator/README.md
index 59f7e929da..ea43377ed2 100644
--- a/spring-boot-modules/spring-boot-actuator/README.md
+++ b/spring-boot-modules/spring-boot-actuator/README.md
@@ -12,3 +12,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [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 b2c7a4d28e..1ccf436bbf 100644
--- a/spring-boot-modules/spring-boot-actuator/pom.xml
+++ b/spring-boot-modules/spring-boot-actuator/pom.xml
@@ -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/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-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-artifacts/pom.xml b/spring-boot-modules/spring-boot-artifacts/pom.xml
index 6bf75491eb..0292dc95cf 100644
--- a/spring-boot-modules/spring-boot-artifacts/pom.xml
+++ b/spring-boot-modules/spring-boot-artifacts/pom.xml
@@ -101,7 +101,7 @@
maven-failsafe-plugin
2.18
-
integration-tests
@@ -110,7 +110,7 @@
verify
-
**/ExternalPropertyFileLoaderIntegrationTest.java
@@ -186,7 +186,7 @@
- com.baeldung.boot.Application
+ com.baeldung.wrapper.DemoApplication
3.1.1
3.3.7-1
2.2
@@ -195,4 +195,4 @@
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-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/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-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/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java
new file mode 100644
index 0000000000..efdff387df
--- /dev/null
+++ b/spring-boot-modules/spring-boot-multiple-datasources/src/main/java/com/baeldung/spring/datasources/MultipleDatasourcesApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.spring.datasources;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MultipleDatasourcesApplication {
+
+ public static void main(String[] 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-swagger/README.md b/spring-boot-modules/spring-boot-swagger/README.md
index ef33be8e07..174bfe626d 100644
--- a/spring-boot-modules/spring-boot-swagger/README.md
+++ b/spring-boot-modules/spring-boot-swagger/README.md
@@ -3,3 +3,5 @@
- [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/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/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-cloud/spring-cloud-archaius/zookeeper-config/pom.xml b/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml
index 7dfb2c7436..bdd75d0635 100644
--- a/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml
+++ b/spring-cloud/spring-cloud-archaius/zookeeper-config/pom.xml
@@ -45,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-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/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-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/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-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-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 52c1f6418e..1390898bf9 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,14 +60,6 @@
org.springframework
spring-expression
-
- org.springframework
- spring-web
-
-
- org.springframework
- spring-webmvc
-
org.springframework.data
spring-data-commons
@@ -137,17 +120,6 @@
net.bytebuddy
byte-buddy
-
-
- javax.servlet
- javax.servlet-api
- provided
-
-
- javax.servlet
- jstl
- runtime
-
com.fasterxml.jackson.core
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/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml
index 69382e5546..f794c3990f 100644
--- a/testing-modules/junit-5/pom.xml
+++ b/testing-modules/junit-5/pom.xml
@@ -134,7 +134,7 @@
- 2.8.2
+ 2.17.1
2.0.9
5.0.1.RELEASE
3.0.0-M3
diff --git a/testing-modules/junit5-annotations/pom.xml b/testing-modules/junit5-annotations/pom.xml
index fad5402242..a4035a23f1 100644
--- a/testing-modules/junit5-annotations/pom.xml
+++ b/testing-modules/junit5-annotations/pom.xml
@@ -39,7 +39,7 @@
- 2.8.2
+ 2.17.1
\ No newline at end of file
diff --git a/testing-modules/test-containers/pom.xml b/testing-modules/test-containers/pom.xml
index 3975b6df31..bd20035eab 100644
--- a/testing-modules/test-containers/pom.xml
+++ b/testing-modules/test-containers/pom.xml
@@ -70,7 +70,7 @@
1.5.0
- 2.12.0
+ 2.17.1
1.11.4
42.2.6
3.141.59