diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 9c5cdb8f2d..0000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "testgitrepo"]
- path = testgitrepo
- url = /home/prd/Development/projects/idea/tutorials/spring-boot/src/main/resources/testgitrepo/
diff --git a/apache-meecrowave/pom.xml b/apache-meecrowave/pom.xml
new file mode 100644
index 0000000000..cf13aa1c1b
--- /dev/null
+++ b/apache-meecrowave/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ com.baeldung
+ apache-meecrowave
+ 0.0.1
+ apache-meecrowave
+ A sample REST API application with Meecrowave
+
+
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.meecrowave
+ meecrowave-core
+ 1.2.1
+
+
+
+ org.apache.meecrowave
+ meecrowave-jpa
+ 1.2.1
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 3.10.0
+
+
+ org.apache.meecrowave
+ meecrowave-junit
+ 1.2.0
+ test
+
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+
+
+
+
+ org.apache.meecrowave
+ meecrowave-maven-plugin
+ 1.2.1
+
+
+
+
\ No newline at end of file
diff --git a/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Article.java b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Article.java
new file mode 100644
index 0000000000..7925e8ff99
--- /dev/null
+++ b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Article.java
@@ -0,0 +1,30 @@
+package com.baeldung.meecrowave;
+
+public class Article {
+ private String name;
+ private String author;
+
+ public Article() {
+ }
+
+ public Article(String name, String author) {
+ this.author = author;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+}
\ No newline at end of file
diff --git a/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java
new file mode 100644
index 0000000000..6cb7012c64
--- /dev/null
+++ b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java
@@ -0,0 +1,32 @@
+package com.baeldung.meecrowave;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+@RequestScoped
+@Path("article")
+public class ArticleEndpoints {
+
+ @Inject
+ ArticleService articleService;
+
+ @GET
+ public Response getArticle() {
+ return Response.ok()
+ .entity(new Article("name", "author"))
+ .build();
+
+ }
+
+ @POST
+ public Response createArticle(Article article) {
+ return Response.status(Status.CREATED)
+ .entity(articleService.createArticle(article))
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java
new file mode 100644
index 0000000000..7bd6b87345
--- /dev/null
+++ b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java
@@ -0,0 +1,10 @@
+package com.baeldung.meecrowave;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ArticleService {
+ public Article createArticle(Article article) {
+ return article;
+ }
+}
diff --git a/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Server.java b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
new file mode 100644
index 0000000000..2aa7d0556f
--- /dev/null
+++ b/apache-meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
@@ -0,0 +1,16 @@
+package com.baeldung.meecrowave;
+
+import org.apache.meecrowave.Meecrowave;
+
+public class Server {
+ public static void main(String[] args) {
+ final Meecrowave.Builder builder = new Meecrowave.Builder();
+ builder.setScanningPackageIncludes("com.baeldung.meecrowave");
+ builder.setJaxrsMapping("/api/*");
+ builder.setJsonpPrettify(true);
+
+ try (Meecrowave meecrowave = new Meecrowave(builder)) {
+ meecrowave.bake().await();
+ }
+ }
+}
diff --git a/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
new file mode 100644
index 0000000000..0dc9773490
--- /dev/null
+++ b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.meecrowave;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.junit.MonoMeecrowave;
+import org.apache.meecrowave.testing.ConfigurationInject;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+@RunWith(MonoMeecrowave.Runner.class)
+public class ArticleEndpointsTest {
+
+ @ConfigurationInject
+ private Meecrowave.Builder config;
+ private static OkHttpClient client;
+
+ @BeforeClass
+ public static void setup() {
+ client = new OkHttpClient();
+ }
+
+ @Test
+ public void whenRetunedArticle_thenCorrect() throws IOException {
+ final String base = "http://localhost:"+config.getHttpPort();
+
+ Request request = new Request.Builder()
+ .url(base+"/article")
+ .build();
+ Response response = client.newCall(request).execute();
+ assertEquals(200, response.code());
+ }
+}
diff --git a/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaLiveTest.java
similarity index 98%
rename from apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
rename to apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaLiveTest.java
index 8b5fe77c6f..eaf0271b55 100644
--- a/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
+++ b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaLiveTest.java
@@ -12,7 +12,7 @@ import org.apache.solr.common.SolrDocumentList;
import org.junit.Before;
import org.junit.Test;
-public class SolrJavaIntegrationTest {
+public class SolrJavaLiveTest {
private SolrJavaIntegration solrJavaIntegration;
diff --git a/aws-lambda/README.md b/aws-lambda/README.md
new file mode 100644
index 0000000000..921b699bdd
--- /dev/null
+++ b/aws-lambda/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+- [Using AWS Lambda with API Gateway](http://www.baeldung.com/aws-lambda-api-gateway)
+- [Introduction to AWS Serverless Application Model](http://www.baeldung.com/aws-serverless)
diff --git a/core-java-8/src/main/java/com/baeldung/datetime/AddHoursToDate.java b/core-java-8/src/main/java/com/baeldung/datetime/AddHoursToDate.java
new file mode 100644
index 0000000000..d9636656b5
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/datetime/AddHoursToDate.java
@@ -0,0 +1,54 @@
+package com.baeldung.datetime;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.commons.lang3.time.DateUtils;
+
+public class AddHoursToDate {
+
+ public Date addHoursToJavaUtilDate(Date date, int hours) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ calendar.add(Calendar.HOUR_OF_DAY, hours);
+ return calendar.getTime();
+ }
+
+ public Date addHoursToDateUsingInstant(Date date, int hours) {
+ return Date.from(date.toInstant()
+ .plus(Duration.ofHours(hours)));
+ }
+
+ public LocalDateTime addHoursToLocalDateTime(LocalDateTime localDateTime, int hours) {
+ return localDateTime.plusHours(hours);
+ }
+
+ public LocalDateTime subtractHoursToLocalDateTime(LocalDateTime localDateTime, int hours) {
+ return localDateTime.minusHours(hours);
+ }
+
+ public ZonedDateTime addHoursToZonedDateTime(ZonedDateTime zonedDateTime, int hours) {
+ return zonedDateTime.plusHours(hours);
+ }
+
+ public ZonedDateTime subtractHoursToZonedDateTime(ZonedDateTime zonedDateTime, int hours) {
+ return zonedDateTime.minusHours(hours);
+ }
+
+ public Instant addHoursToInstant(Instant instant, int hours) {
+ return instant.plus(hours, ChronoUnit.HOURS);
+ }
+
+ public Instant subtractHoursToInstant(Instant instant, int hours) {
+ return instant.minus(hours, ChronoUnit.HOURS);
+ }
+
+ public Date addHoursWithApacheCommons(Date date, int hours) {
+ return DateUtils.addHours(date, hours);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/datetime/AddHoursToDateUnitTest.java b/core-java-8/src/test/java/com/baeldung/datetime/AddHoursToDateUnitTest.java
new file mode 100644
index 0000000000..aa34367f30
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/datetime/AddHoursToDateUnitTest.java
@@ -0,0 +1,116 @@
+package com.baeldung.datetime;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.Month;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.junit.Test;
+
+public class AddHoursToDateUnitTest {
+
+ private final AddHoursToDate addHoursToDateObj = new AddHoursToDate();
+
+ @Test
+ public void givenJavaUtilDate_whenPositiveHours_thenAddHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursToJavaUtilDate(actualDate, 2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenJavaUtilDate_whenNegativeHours_thenMinusHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 3, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursToJavaUtilDate(actualDate, -2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenJavaUtilDate_whenUsingToInstantAndPostiveHours_thenAddHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursToDateUsingInstant(actualDate, 2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenJavaUtilDate_whenUsingToInstantAndNegativeHours_thenAddHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 3, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursToDateUsingInstant(actualDate, -2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenLocalDateTime_whenUsingAddHoursToLocalDateTime_thenAddHours() {
+ LocalDateTime actualDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 5, 0);
+ LocalDateTime expectedDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 7, 0);
+
+ assertThat(addHoursToDateObj.addHoursToLocalDateTime(actualDateTime, 2)).isEqualTo(expectedDateTime);
+ }
+
+ @Test
+ public void givenLocalDateTime_whenUsingMinusHoursToLocalDateTime_thenMinusHours() {
+ LocalDateTime actualDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 5, 0);
+ LocalDateTime expectedDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 3, 0);
+
+ assertThat(addHoursToDateObj.subtractHoursToLocalDateTime(actualDateTime, 2)).isEqualTo(expectedDateTime);
+ }
+
+ @Test
+ public void givenZonedDateTime_whenUsingAddHoursToZonedDateTime_thenAddHours() {
+ ZonedDateTime actualZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 5, 0), ZoneId.systemDefault());
+ ZonedDateTime expectedZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 7, 0), ZoneId.systemDefault());
+
+ assertThat(addHoursToDateObj.addHoursToZonedDateTime(actualZonedDateTime, 2)).isEqualTo(expectedZonedDateTime);
+ }
+
+ @Test
+ public void givenZonedDateTime_whenUsingMinusHoursToZonedDateTime_thenMinusHours() {
+ ZonedDateTime actualZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 5, 0), ZoneId.systemDefault());
+ ZonedDateTime expectedZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 3, 0), ZoneId.systemDefault());
+
+ assertThat(addHoursToDateObj.subtractHoursToZonedDateTime(actualZonedDateTime, 2)).isEqualTo(expectedZonedDateTime);
+ }
+
+ @Test
+ public void givenJavaUtilDate_whenUsingPositiveHrsAndAddHoursWithApacheCommons_thenAddHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursWithApacheCommons(actualDate, 2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenJavaUtilDate_whenUsingNegativeHrsAndAddHoursWithApacheCommons_thenMinusHours() {
+ Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
+ Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
+
+ assertThat(addHoursToDateObj.addHoursWithApacheCommons(actualDate, -2)).isEqualTo(expectedDate);
+ }
+
+ @Test
+ public void givenInstant_whenUsingAddHoursToInstant_thenAddHours() {
+ Instant actualValue = Instant.parse("2018-06-25T05:12:35Z");
+ Instant expectedValue = Instant.parse("2018-06-25T07:12:35Z");
+
+ assertThat(addHoursToDateObj.addHoursToInstant(actualValue, 2)).isEqualTo(expectedValue);
+ }
+
+ @Test
+ public void givenInstant_whenUsingSubtractHoursToInstant_thenMinusHours() {
+ Instant actualValue = Instant.parse("2018-06-25T07:12:35Z");
+ Instant expectedValue = Instant.parse("2018-06-25T05:12:35Z");
+
+ assertThat(addHoursToDateObj.subtractHoursToInstant(actualValue, 2)).isEqualTo(expectedValue);
+ }
+
+}
diff --git a/core-java/README.md b/core-java/README.md
index 3aa50e5b86..16378bc169 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -166,3 +166,4 @@
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension)
- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object)
+- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
diff --git a/core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java b/core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java
new file mode 100644
index 0000000000..b557ccf31a
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java
@@ -0,0 +1,60 @@
+package com.baeldung.encrypt;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+import java.io.*;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+class FileEncrypterDecrypter {
+
+ private SecretKey secretKey;
+ private Cipher cipher;
+
+ FileEncrypterDecrypter(SecretKey secretKey, String cipher) throws NoSuchPaddingException, NoSuchAlgorithmException {
+ this.secretKey = secretKey;
+ this.cipher = Cipher.getInstance(cipher);
+ }
+
+ void encrypt(String content, String fileName) throws InvalidKeyException, IOException {
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ byte[] iv = cipher.getIV();
+
+ try (
+ FileOutputStream fileOut = new FileOutputStream(fileName);
+ CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher)
+ ) {
+ fileOut.write(iv);
+ cipherOut.write(content.getBytes());
+ }
+
+ }
+
+ String decrypt(String fileName) throws InvalidAlgorithmParameterException, InvalidKeyException, IOException {
+
+ String content;
+
+ try (FileInputStream fileIn = new FileInputStream(fileName)) {
+ byte[] fileIv = new byte[16];
+ fileIn.read(fileIv);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(fileIv));
+
+ try (
+ CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
+ InputStreamReader inputReader = new InputStreamReader(cipherIn);
+ BufferedReader reader = new BufferedReader(inputReader)
+ ) {
+
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ content = sb.toString();
+ }
+
+ }
+ return content;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java b/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java
new file mode 100644
index 0000000000..138916ec60
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java
@@ -0,0 +1,20 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Arithmetic {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(Arithmetic.class);
+
+ public static void main(String[] args) {
+
+ try {
+ int result = 30 / 0; // Trying to divide by zero
+ } catch (ArithmeticException e) {
+ LOGGER.error("ArithmeticException caught!");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java b/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java
new file mode 100644
index 0000000000..93b53f284c
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java
@@ -0,0 +1,24 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArrayIndexOutOfBounds {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ArrayIndexOutOfBounds.class);
+
+ public static void main(String[] args) {
+
+ int[] nums = new int[] { 1, 2, 3 };
+
+ try {
+ int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
+ int numFromGreaterIndex = nums[4]; // Trying to access at greater index
+ int numFromLengthIndex = nums[3]; // Trying to access at index equal to size of the array
+ } catch (ArrayIndexOutOfBoundsException e) {
+ LOGGER.error("ArrayIndexOutOfBoundsException caught");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java b/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java
new file mode 100644
index 0000000000..183f8f54a3
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java
@@ -0,0 +1,36 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class Animal {
+
+}
+
+class Dog extends Animal {
+
+}
+
+class Lion extends Animal {
+
+}
+
+public class ClassCast {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ClassCast.class);
+
+ public static void main(String[] args) {
+
+ try {
+ Animal animalOne = new Dog(); // At runtime the instance is dog
+ Dog bruno = (Dog) animalOne; // Downcasting
+
+ Animal animalTwo = new Lion(); // At runtime the instance is animal
+ Dog tommy = (Dog) animalTwo; // Downcasting
+ } catch (ClassCastException e) {
+ LOGGER.error("ClassCastException caught!");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java b/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java
new file mode 100644
index 0000000000..bb9e0bf4ac
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java
@@ -0,0 +1,25 @@
+package com.baeldung.exceptions;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileNotFound {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(FileNotFound.class);
+
+ public static void main(String[] args) {
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(new File("/invalid/file/location")));
+ } catch (FileNotFoundException e) {
+ LOGGER.error("FileNotFoundException caught!");
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java b/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java
new file mode 100644
index 0000000000..ab46c83da4
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java
@@ -0,0 +1,28 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GlobalExceptionHandler {
+
+ public static void main(String[] args) {
+
+ Handler globalExceptionHandler = new Handler();
+ Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
+ new GlobalExceptionHandler().performArithmeticOperation(10, 0);
+ }
+
+ public int performArithmeticOperation(int num1, int num2) {
+ return num1/num2;
+ }
+
+}
+
+class Handler implements Thread.UncaughtExceptionHandler {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);
+
+ public void uncaughtException(Thread t, Throwable e) {
+ LOGGER.info("Unhandled exception caught!");
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java b/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java
new file mode 100644
index 0000000000..801536cb2d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java
@@ -0,0 +1,18 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IllegalArgument {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(IllegalArgument.class);
+
+ public static void main(String[] args) {
+ try {
+ Thread.sleep(-1000);
+ } catch (InterruptedException e) {
+ LOGGER.error("IllegalArgumentException caught!");
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java b/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java
new file mode 100644
index 0000000000..e8ddcea3c2
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java
@@ -0,0 +1,32 @@
+package com.baeldung.exceptions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IllegalState {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(IllegalState.class);
+
+ public static void main(String[] args) {
+
+ List intList = new ArrayList<>();
+
+ for (int i = 0; i < 10; i++) {
+ intList.add(i);
+ }
+
+ Iterator intListIterator = intList.iterator(); // Initialized with index at -1
+
+ try {
+ intListIterator.remove(); // IllegalStateException
+ } catch (IllegalStateException e) {
+ LOGGER.error("IllegalStateException caught!");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java b/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java
new file mode 100644
index 0000000000..319fd33591
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java
@@ -0,0 +1,28 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class ChildThread extends Thread {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ChildThread.class);
+
+ public void run() {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ LOGGER.error("InterruptedException caught!");
+ }
+ }
+
+}
+
+public class InterruptedExceptionExample {
+
+ public static void main(String[] args) throws InterruptedException {
+ ChildThread childThread = new ChildThread();
+ childThread.start();
+ childThread.interrupt();
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java b/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java
new file mode 100644
index 0000000000..57fcddf76b
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java
@@ -0,0 +1,25 @@
+package com.baeldung.exceptions;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MalformedURL {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(MalformedURL.class);
+
+ public static void main(String[] args) {
+
+ URL baeldungURL = null;
+
+ try {
+ baeldungURL = new URL("malformedurl");
+ } catch (MalformedURLException e) {
+ LOGGER.error("MalformedURLException caught!");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java b/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java
new file mode 100644
index 0000000000..2402a786a9
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java
@@ -0,0 +1,36 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NullPointer {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(NullPointer.class);
+
+ public static void main(String[] args) {
+
+ Person personObj = null;
+
+ try {
+ String name = personObj.personName; // Accessing the field of a null object
+ personObj.personName = "Jon Doe"; // Modifying the field of a null object
+ } catch (NullPointerException e) {
+ LOGGER.error("NullPointerException caught!");
+ }
+
+ }
+}
+
+class Person {
+
+ public String personName;
+
+ public String getPersonName() {
+ return personName;
+ }
+
+ public void setPersonName(String personName) {
+ this.personName = personName;
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java b/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java
new file mode 100644
index 0000000000..7050e70aee
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java
@@ -0,0 +1,23 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NumberFormat {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(NumberFormat.class);
+
+ public static void main(String[] args) {
+
+ String str1 = "100ABCD";
+
+ try {
+ int x = Integer.parseInt(str1); // Converting string with inappropriate format
+ int y = Integer.valueOf(str1);
+ } catch (NumberFormatException e) {
+ LOGGER.error("NumberFormatException caught!");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java b/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java
new file mode 100644
index 0000000000..f7fb4c91e4
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java
@@ -0,0 +1,25 @@
+package com.baeldung.exceptions;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ParseExceptionExample {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(ParseExceptionExample.class);
+
+ public static void main(String[] args) {
+
+ DateFormat format = new SimpleDateFormat("MM, dd, yyyy");
+
+ try {
+ format.parse("01, , 2010");
+ } catch (ParseException e) {
+ LOGGER.error("ParseException caught!");
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java b/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java
new file mode 100644
index 0000000000..bc297be498
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java
@@ -0,0 +1,23 @@
+package com.baeldung.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StringIndexOutOfBounds {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(StringIndexOutOfBounds.class);
+
+ public static void main(String[] args) {
+
+ String str = "Hello World";
+
+ try {
+ char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
+ char charAtLengthIndex = str.charAt(11); // Trying to access at index equal to size of the string
+ } catch (StringIndexOutOfBoundsException e) {
+ LOGGER.error("StringIndexOutOfBoundsException caught");
+ }
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/gregorian/calendar/GregorianCalendarExample.java b/core-java/src/main/java/com/baeldung/gregorian/calendar/GregorianCalendarExample.java
new file mode 100644
index 0000000000..d8018cefd5
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/gregorian/calendar/GregorianCalendarExample.java
@@ -0,0 +1,69 @@
+package com.baeldung.gregorian.calendar;
+
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+public class GregorianCalendarExample {
+
+
+ public Date setMonth(GregorianCalendar calendar, int amount) {
+ calendar.set(Calendar.MONTH, amount);
+ return calendar.getTime();
+ }
+
+
+ public Date rollAdd(GregorianCalendar calendar, int amount) {
+ calendar.roll(GregorianCalendar.MONTH, amount);
+ return calendar.getTime();
+ }
+
+ public boolean isLeapYearExample(int year) {
+ GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
+ return cal.isLeapYear(year);
+ }
+
+
+
+ public Date subtractDays(GregorianCalendar calendar, int daysToSubtract) {
+ GregorianCalendar cal = calendar;
+ cal.add(Calendar.DATE, -daysToSubtract);
+ return cal.getTime();
+ }
+
+ public Date addDays(GregorianCalendar calendar, int daysToAdd) {
+ GregorianCalendar cal = calendar;
+ cal.add(Calendar.DATE, daysToAdd);
+ return cal.getTime();
+ }
+
+ public XMLGregorianCalendar toXMLGregorianCalendar(GregorianCalendar calendar) throws DatatypeConfigurationException {
+ DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+ return datatypeFactory.newXMLGregorianCalendar(calendar);
+ }
+
+ public Date toDate(XMLGregorianCalendar calendar) {
+ return calendar.toGregorianCalendar()
+ .getTime();
+ }
+
+ public int compareDates(GregorianCalendar firstDate, GregorianCalendar secondDate) {
+ return firstDate.compareTo(secondDate);
+ }
+
+ public String formatDate(GregorianCalendar calendar) {
+ return calendar.toZonedDateTime()
+ .format(DateTimeFormatter.ofPattern("d MMM uuuu"));
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java b/core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java
new file mode 100644
index 0000000000..b767a24b16
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.encrypt;
+
+import org.junit.Test;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import java.io.File;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class FileEncrypterDecrypterIntegrationTest {
+
+ @Test
+ public void givenStringAndFilename_whenEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
+ String originalContent = "foobar";
+ SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
+
+ FileEncrypterDecrypter fileEncrypterDecrypter = new FileEncrypterDecrypter(secretKey, "AES/CBC/PKCS5Padding");
+ fileEncrypterDecrypter.encrypt(originalContent, "baz.enc");
+
+ String decryptedContent = fileEncrypterDecrypter.decrypt("baz.enc");
+ assertThat(decryptedContent, is(originalContent));
+
+ new File("baz.enc").delete(); // cleanup
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java b/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java
new file mode 100644
index 0000000000..394de9c576
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java
@@ -0,0 +1,64 @@
+package com.baeldung.exceptions;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.slf4j.LoggerFactory;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.Appender;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GlobalExceptionHandlerUnitTest {
+
+ @Mock
+ private Appender mockAppender;
+
+ @Captor
+ private ArgumentCaptor captorLoggingEvent;
+
+ @Before
+ public void setup() {
+ final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+ logger.addAppender(mockAppender);
+
+ Handler globalExceptionHandler = new Handler();
+ Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
+ }
+
+ @After
+ public void teardown() {
+ final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+ logger.detachAppender(mockAppender);
+ }
+
+ @Test
+ public void whenArithmeticException_thenUseUncaughtExceptionHandler() throws InterruptedException {
+
+ Thread globalExceptionHandlerThread = new Thread() {
+ public void run() {
+ GlobalExceptionHandler globalExceptionHandlerObj = new GlobalExceptionHandler();
+ globalExceptionHandlerObj.performArithmeticOperation(99, 0);
+ }
+ };
+
+ globalExceptionHandlerThread.start();
+ globalExceptionHandlerThread.join();
+
+ verify(mockAppender).doAppend(captorLoggingEvent.capture());
+ LoggingEvent loggingEvent = captorLoggingEvent.getValue();
+
+ assertThat(loggingEvent.getLevel()).isEqualTo(Level.INFO);
+ assertThat(loggingEvent.getFormattedMessage()).isEqualTo("Unhandled exception caught!");
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/gregorian/calendar/GregorianCalendarTester.java b/core-java/src/test/java/com/baeldung/gregorian/calendar/GregorianCalendarTester.java
new file mode 100644
index 0000000000..a1d084cf9a
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/gregorian/calendar/GregorianCalendarTester.java
@@ -0,0 +1,228 @@
+package com.baeldung.gregorian.calendar;
+
+import static org.junit.Assert.*;
+
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.junit.Test;
+
+import com.baeldung.gregorian.calendar.GregorianCalendarExample;
+
+public class GregorianCalendarTester {
+
+ @Test
+ public void test_Calendar_Return_Type_Valid() {
+ Calendar calendar = Calendar.getInstance();
+ assert ("gregory".equals(calendar.getCalendarType()));
+ }
+
+ @Test
+ public void test_Calendar_Return_Type_InValid() {
+ Calendar calendar = Calendar.getInstance();
+ assertNotEquals("gregorys", calendar.getCalendarType());
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void test_Class_Cast_Exception() {
+ TimeZone tz = TimeZone.getTimeZone("GMT+9:00");
+ Locale loc = new Locale("ja", "JP", "JP");
+ Calendar calendar = Calendar.getInstance(loc);
+ GregorianCalendar gc = (GregorianCalendar) calendar;
+ }
+
+ @Test
+ public void test_Getting_Calendar_information() {
+ GregorianCalendar calendar = new GregorianCalendar(2018, 5, 28);
+ assertTrue(false == calendar.isLeapYear(calendar.YEAR));
+ assertTrue(52 == calendar.getWeeksInWeekYear());
+ assertTrue(2018 == calendar.getWeekYear());
+ assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
+ assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
+ assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
+ assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
+ assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
+ assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
+ assertTrue(52 == calendar.getWeeksInWeekYear());
+ }
+
+ @Test
+ public void test_Compare_Date_FirstDate_Greater_SecondDate() {
+ GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar secondDate = new GregorianCalendar(2018, 5, 28);
+ assertTrue(1 == firstDate.compareTo(secondDate));
+ }
+
+
+ @Test
+ public void test_Compare_Date_FirstDate_Smaller_SecondDate() {
+ GregorianCalendar firstDate = new GregorianCalendar(2018, 5, 28);
+ GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
+ assertTrue(-1 == firstDate.compareTo(secondDate));
+ }
+
+ @Test
+ public void test_Compare_Date_Both_Dates_Equal() {
+ GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
+ assertTrue(0 == firstDate.compareTo(secondDate));
+ }
+
+ @Test
+ public void test_date_format() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendar = new GregorianCalendar(2018, 6, 28);
+ assertEquals("28 Jul 2018", calendarDemo.formatDate(calendar));
+ }
+
+ @Test
+ public void test_dateFormatdMMMuuuu() {
+ String expectedDate = new GregorianCalendar(2018, 6, 28).toZonedDateTime()
+ .format(DateTimeFormatter.ofPattern("d MMM uuuu"));
+ assertEquals("28 Jul 2018", expectedDate);
+ }
+
+ @Test
+ public void test_addDays() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.add(Calendar.DATE, 1);
+ Date expectedDate = calendarExpected.getTime();
+ assertEquals(expectedDate, calendarDemo.addDays(calendarActual, 1));
+ }
+
+ @Test
+ public void test_whenAddOneDay_thenMonthIsChanged() {
+ final int finalDay1 = 1;
+ final int finalMonthJul = 6;
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 30);
+ calendarExpected.add(Calendar.DATE, 1);
+ System.out.println(calendarExpected.getTime());
+ assertEquals(calendarExpected.get(Calendar.DATE), finalDay1);
+ assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthJul);
+ }
+
+ @Test
+ public void test_whenSubtractOneDay_thenMonthIsChanged() {
+ final int finalDay31 = 31;
+ final int finalMonthMay = 4;
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 1);
+ calendarExpected.add(Calendar.DATE, -1);
+ assertEquals(calendarExpected.get(Calendar.DATE), finalDay31);
+ assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthMay);
+ }
+
+ @Test
+ public void test_subDays() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.add(Calendar.DATE, -1);
+ Date expectedDate = calendarExpected.getTime();
+ assertEquals(expectedDate, calendarDemo.subtractDays(calendarActual, 1));
+ }
+
+ @Test
+ public void test_rollAdd() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.roll(Calendar.MONTH, 8);
+ Date expectedDate = calendarExpected.getTime();
+ assertEquals(expectedDate, calendarDemo.rollAdd(calendarActual, 8));
+ }
+
+ @Test
+ public void test_whenRollUpOneMonth_thenYearIsUnchanged() {
+ final int rolledUpMonthJuly = 7, orginalYear2018 = 2018;
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.roll(Calendar.MONTH, 1);
+ assertEquals(calendarExpected.get(Calendar.MONTH), rolledUpMonthJuly);
+ assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
+ }
+
+ @Test
+ public void test_whenRollDownOneMonth_thenYearIsUnchanged() {
+ final int rolledDownMonthJune = 5, orginalYear2018 = 2018;
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.roll(Calendar.MONTH, -1);
+ assertEquals(calendarExpected.get(Calendar.MONTH), rolledDownMonthJune);
+ assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
+ }
+
+ @Test
+ public void test_rollSubtract() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.roll(Calendar.MONTH, -8);
+ Date expectedDate = calendarExpected.getTime();
+ assertEquals(expectedDate, calendarDemo.rollAdd(calendarActual, -8));
+ }
+
+ @Test
+ public void test_setMonth() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.set(Calendar.MONTH, 3);
+ Date expectedDate = calendarExpected.getTime();
+ assertEquals(expectedDate, calendarDemo.setMonth(calendarActual, 3));
+ }
+
+ @Test
+ public void test_setMonthApril() {
+ final int setMonthApril = 3, orginalYear2018 = 2018, originalDate28 = 28;
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ calendarExpected.set(Calendar.MONTH, 3);
+ assertEquals(calendarExpected.get(Calendar.MONTH), setMonthApril);
+ assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
+ assertEquals(calendarExpected.get(Calendar.DATE), originalDate28);
+ }
+
+ @Test
+ public void test_toXMLGregorianCalendar() throws DatatypeConfigurationException {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
+ XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
+ .newXMLGregorianCalendar(calendarExpected);
+ assertEquals(expectedXMLGregorianCalendar,
+ calendarDemo.toXMLGregorianCalendar(calendarActual));
+ }
+
+ @Test
+ public void test_isLeapYear_True() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ assertEquals(true, calendarDemo.isLeapYearExample(2016));
+
+ }
+
+ @Test
+ public void test_isLeapYear_False() {
+ GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
+ assertEquals(false, calendarDemo.isLeapYearExample(2018));
+
+ }
+
+ @Test
+ public void test_toDate() throws DatatypeConfigurationException {
+ GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
+ DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+ XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
+ .newXMLGregorianCalendar(calendarActual);
+ expectedXMLGregorianCalendar.toGregorianCalendar().getTime();
+ assertEquals(calendarActual.getTime(),
+ expectedXMLGregorianCalendar.toGregorianCalendar().getTime() );
+ }
+}
diff --git a/core-kotlin/README.md b/core-kotlin/README.md
index 69ad0a7dae..4695d12a06 100644
--- a/core-kotlin/README.md
+++ b/core-kotlin/README.md
@@ -32,3 +32,4 @@
- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
+- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
diff --git a/data-structures/src/main/java/com/baeldung/trie/Trie.java b/data-structures/src/main/java/com/baeldung/trie/Trie.java
index dd51d97b2d..dac1a64733 100644
--- a/data-structures/src/main/java/com/baeldung/trie/Trie.java
+++ b/data-structures/src/main/java/com/baeldung/trie/Trie.java
@@ -1,13 +1,13 @@
package com.baeldung.trie;
-public class Trie {
+class Trie {
private TrieNode root;
Trie() {
root = new TrieNode();
}
- public void insert(String word) {
+ void insert(String word) {
TrieNode current = root;
for (int i = 0; i < word.length(); i++) {
@@ -16,11 +16,11 @@ public class Trie {
current.setEndOfWord(true);
}
- public boolean delete(String word) {
+ boolean delete(String word) {
return delete(root, word, 0);
}
- public boolean containsNode(String word) {
+ boolean containsNode(String word) {
TrieNode current = root;
for (int i = 0; i < word.length(); i++) {
@@ -34,7 +34,7 @@ public class Trie {
return current.isEndOfWord();
}
- public boolean isEmpty() {
+ boolean isEmpty() {
return root == null;
}
@@ -51,7 +51,7 @@ public class Trie {
if (node == null) {
return false;
}
- boolean shouldDeleteCurrentNode = delete(node, word, index + 1);
+ boolean shouldDeleteCurrentNode = delete(node, word, index + 1) && !node.isEndOfWord();
if (shouldDeleteCurrentNode) {
current.getChildren().remove(ch);
diff --git a/data-structures/src/main/java/com/baeldung/trie/TrieNode.java b/data-structures/src/main/java/com/baeldung/trie/TrieNode.java
index 25dc753950..73dcdb63f5 100644
--- a/data-structures/src/main/java/com/baeldung/trie/TrieNode.java
+++ b/data-structures/src/main/java/com/baeldung/trie/TrieNode.java
@@ -4,28 +4,18 @@ import java.util.HashMap;
import java.util.Map;
class TrieNode {
- private Map children;
+ private final Map children = new HashMap<>();
private boolean endOfWord;
- public TrieNode() {
- children = new HashMap<>();
- endOfWord = false;
- }
-
- public Map getChildren() {
+ Map getChildren() {
return children;
}
- public void setChildren(Map children) {
- this.children = children;
- }
-
- public boolean isEndOfWord() {
+ boolean isEndOfWord() {
return endOfWord;
}
- public void setEndOfWord(boolean endOfWord) {
+ void setEndOfWord(boolean endOfWord) {
this.endOfWord = endOfWord;
}
-
}
\ No newline at end of file
diff --git a/data-structures/src/test/java/com/baeldung/trie/TrieTest.java b/data-structures/src/test/java/com/baeldung/trie/TrieTest.java
index be7e5575d8..6f7073651e 100644
--- a/data-structures/src/test/java/com/baeldung/trie/TrieTest.java
+++ b/data-structures/src/test/java/com/baeldung/trie/TrieTest.java
@@ -1,6 +1,7 @@
package com.baeldung.trie;
import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -53,6 +54,19 @@ public class TrieTest {
assertFalse(trie.containsNode("Programming"));
}
+ @Test
+ public void givenATrie_whenDeletingOverlappingElements_thenDontDeleteSubElement() {
+
+ Trie trie1 = new Trie();
+
+ trie1.insert("pie");
+ trie1.insert("pies");
+
+ trie1.delete("pies");
+
+ Assertions.assertTrue(trie1.containsNode("pie"));
+ }
+
private Trie createExampleTrie() {
Trie trie = new Trie();
diff --git a/ethereum/pom.xml b/ethereum/pom.xml
index 02b9e5afe1..f07ed2c6a0 100644
--- a/ethereum/pom.xml
+++ b/ethereum/pom.xml
@@ -1,47 +1,17 @@
+ 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.ethereum
ethereum
0.0.1-SNAPSHOT
ethereum
-
-
-
-
- UTF-8
- 1.8
- 8.5.4
- 1.5.0-RELEASE
- 3.3.1
- 5.0.5.RELEASE
- 1.5.6.RELEASE
- 2.18.1
- 1.10.19
- 2.5.0
- 1.3
- 2.9.3
- 2.3.1
- 3.1.0
- 2.4.0
- 1.2
- 4.12
- 1.2.3
- 1.7.25
-
-
-
-
- Ethereum
- Ethereum
- https://dl.bintray.com/ethereum/maven/
-
-
+
+ parent-spring-5
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-spring-5
+
@@ -64,7 +34,7 @@
-
+
org.springframework
spring-core
${springframework.version}
@@ -199,7 +169,9 @@
${jsonpath.version}
+
+ ethereum
maven-compiler-plugin
@@ -222,21 +194,36 @@
false
-
- org.apache.maven.plugins
- maven-surefire-plugin
- ${maven-surefire.version}
-
-
- install
- install
-
- test
-
-
-
-
- ethereum
+
+
+
+ Ethereum
+ Ethereum
+ https://dl.bintray.com/ethereum/maven/
+
+
+
+
+ UTF-8
+ 1.8
+ 8.5.4
+ 1.5.0-RELEASE
+ 3.3.1
+ 5.0.5.RELEASE
+ 1.5.6.RELEASE
+ 1.10.19
+ 2.5.0
+ 1.3
+ 2.9.3
+ 2.3.1
+ 3.1.0
+ 2.4.0
+ 1.2
+ 4.12
+ 1.2.3
+ 1.7.25
+
+
diff --git a/javax-servlet-init-params/pom.xml b/javax-servlet-init-params/pom.xml
deleted file mode 100644
index 4f766a7e2c..0000000000
--- a/javax-servlet-init-params/pom.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
- 4.0.0
- com.baeldung.javax-servlet-init-params
- javax-servlet-init-params
- 1.0
-
-
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
-
-
-
-
- junit
- junit
- 4.12
- test
-
-
- org.assertj
- assertj-core
- 3.9.1
- test
-
-
- org.hamcrest
- hamcrest-core
- 1.3
- test
-
-
- org.mockito
- mockito-core
- 2.18.3
- test
-
-
- javax
- javaee-web-api
- 7.0
- provided
-
-
- jstl
- jstl
- 1.2
-
-
- javax.el
- el-api
- 2.2
-
-
-
\ No newline at end of file
diff --git a/javax-servlet-init-params/src/main/webapp/WEB-INF/web.xml b/javax-servlet-init-params/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 1b801171b3..0000000000
--- a/javax-servlet-init-params/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- province
- Mendoza
-
-
- country
- Argentina
-
-
diff --git a/javax-servlets/pom.xml b/javax-servlets/pom.xml
index f64ce67a1f..fadf0216ce 100644
--- a/javax-servlets/pom.xml
+++ b/javax-servlets/pom.xml
@@ -1,79 +1,104 @@
-
-
- 4.0.0
- javax-servlets
- 1.0-SNAPSHOT
-
-
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
-
-
-
-
-
- commons-fileupload
- commons-fileupload
- 1.3.3
-
-
- commons-io
- commons-io
- 2.6
-
-
-
-
- javax.servlet
- javax.servlet-api
- 4.0.1
-
-
- javax.servlet.jsp.jstl
- jstl-api
- 1.2
-
-
- javax.servlet.jsp
- javax.servlet.jsp-api
- 2.3.1
-
-
- javax.servlet
- jstl
- 1.2
-
-
-
- org.apache.httpcomponents
- httpclient
- ${org.apache.httpcomponents.version}
- test
-
-
- commons-logging
- commons-logging
-
-
-
-
- com.google.code.gson
- gson
- ${gson.version}
-
-
- org.springframework
- spring-test
- ${spring-test.version}
- test
-
-
-
-
- 4.5.3
- 5.0.5.RELEASE
- 2.8.2
-
-
\ No newline at end of file
+
+
+ 4.0.0
+ com.baeldung.javax-servlets
+ javax-servlets
+ 1.0-SNAPSHOT
+ war
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.9.1
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ 1.3
+ test
+
+
+ org.mockito
+ mockito-core
+ 2.18.3
+ test
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.3.3
+
+
+ commons-io
+ commons-io
+ 2.6
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+
+
+ javax.servlet.jsp.jstl
+ jstl-api
+ 1.2
+
+
+ javax.servlet.jsp
+ javax.servlet.jsp-api
+ 2.3.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${org.apache.httpcomponents.version}
+ test
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+ org.springframework
+ spring-test
+ ${spring-test.version}
+ test
+
+
+
+ 3.1.0
+ 4.5.3
+ 5.0.5.RELEASE
+ 2.8.2
+
+
diff --git a/javax-servlet-init-params/src/main/java/com/baeldung/servlets/UserServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java
similarity index 97%
rename from javax-servlet-init-params/src/main/java/com/baeldung/servlets/UserServlet.java
rename to javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java
index e195aa092a..269cee3922 100644
--- a/javax-servlet-init-params/src/main/java/com/baeldung/servlets/UserServlet.java
+++ b/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java
@@ -1,49 +1,49 @@
-package com.baeldung.servlets;
-
-import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebInitParam;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"}, initParams={
- @WebInitParam(name="name", value="Not provided"),
- @WebInitParam(name="email", value="Not provided")})
-public class UserServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- forwardRequest(request, response, "/WEB-INF/jsp/result.jsp");
- }
-
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- request.setAttribute("name", getRequestParameter(request, "name"));
- request.setAttribute("email", getRequestParameter(request, "email"));
- request.setAttribute("province", getContextParameter("province"));
- request.setAttribute("country", getContextParameter("country"));
- }
-
- protected String getRequestParameter(HttpServletRequest request, String name) {
- String param = request.getParameter(name);
- return !param.isEmpty() ? param : getInitParameter(name);
- }
-
- protected String getContextParameter(String name) {
- return getServletContext().getInitParameter(name);
- }
-
- protected void forwardRequest(HttpServletRequest request, HttpServletResponse response, String path)
- throws ServletException, IOException {
- request.getRequestDispatcher(path).forward(request, response);
- }
+package com.baeldung.servlets;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebInitParam;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"}, initParams={
+ @WebInitParam(name="name", value="Not provided"),
+ @WebInitParam(name="email", value="Not provided")})
+public class UserServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ processRequest(request, response);
+ forwardRequest(request, response, "/WEB-INF/jsp/result.jsp");
+ }
+
+ protected void processRequest(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ request.setAttribute("name", getRequestParameter(request, "name"));
+ request.setAttribute("email", getRequestParameter(request, "email"));
+ request.setAttribute("province", getContextParameter("province"));
+ request.setAttribute("country", getContextParameter("country"));
+ }
+
+ protected String getRequestParameter(HttpServletRequest request, String name) {
+ String param = request.getParameter(name);
+ return !param.isEmpty() ? param : getInitParameter(name);
+ }
+
+ protected String getContextParameter(String name) {
+ return getServletContext().getInitParameter(name);
+ }
+
+ protected void forwardRequest(HttpServletRequest request, HttpServletResponse response, String path)
+ throws ServletException, IOException {
+ request.getRequestDispatcher(path).forward(request, response);
+ }
}
\ No newline at end of file
diff --git a/javax-servlet-init-params/src/main/webapp/WEB-INF/jsp/result.jsp b/javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp
similarity index 100%
rename from javax-servlet-init-params/src/main/webapp/WEB-INF/jsp/result.jsp
rename to javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp
diff --git a/javax-servlets/src/main/webapp/WEB-INF/web.xml b/javax-servlets/src/main/webapp/WEB-INF/web.xml
index c9a06ac52d..383be7ff25 100644
--- a/javax-servlets/src/main/webapp/WEB-INF/web.xml
+++ b/javax-servlets/src/main/webapp/WEB-INF/web.xml
@@ -1,9 +1,17 @@
+
-
+
+ province
+ Mendoza
+
+
+ country
+ Argentina
+
404
/error-404.html
diff --git a/javax-servlet-init-params/src/main/webapp/index.jsp b/javax-servlets/src/main/webapp/user.jsp
similarity index 90%
rename from javax-servlet-init-params/src/main/webapp/index.jsp
rename to javax-servlets/src/main/webapp/user.jsp
index ca41942e5d..c6e1bb69f9 100644
--- a/javax-servlet-init-params/src/main/webapp/index.jsp
+++ b/javax-servlets/src/main/webapp/user.jsp
@@ -3,7 +3,7 @@
- Context and Initialization Servlet Parameters
+ Context and Servlet Initialization Parameters
diff --git a/javax-servlets/src/test/java/com/baeldung/servlets/FormServletLiveTest.java b/javax-servlets/src/test/java/com/baeldung/test/FormServletLiveTest.java
similarity index 100%
rename from javax-servlets/src/test/java/com/baeldung/servlets/FormServletLiveTest.java
rename to javax-servlets/src/test/java/com/baeldung/test/FormServletLiveTest.java
diff --git a/javax-servlet-init-params/src/test/java/com/baeldung/test/UserServletUnitTest.java b/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java
similarity index 95%
rename from javax-servlet-init-params/src/test/java/com/baeldung/test/UserServletUnitTest.java
rename to javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java
index ef3d877dd7..d4c93791d2 100644
--- a/javax-servlet-init-params/src/test/java/com/baeldung/test/UserServletUnitTest.java
+++ b/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java
@@ -1,52 +1,52 @@
-package com.baeldung.test;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import static org.assertj.core.api.Assertions.assertThat;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class UserServletUnitTest {
-
- private static HttpServletRequest request;
- private static HttpServletResponse response;
-
-
- @BeforeClass
- public static void setUpHttpServletRequestMockInstance() {
- request = mock(HttpServletRequest.class);
- }
-
- @BeforeClass
- public static void setUpHttpServletResponsetMockInstance() {
- response = mock(HttpServletResponse.class);
- }
-
- @Test
- public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenCalledAtLeastOnce() {
- request.getParameter("name");
- verify(request, atLeast(1)).getParameter("name");
- }
-
- @Test
- public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenOneAssertion() {
- when(request.getParameter("name")).thenReturn("username");
- assertThat(request.getParameter("name")).isEqualTo("username");
- }
-
- @Test
- public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenCalledAtLeastOnce() {
- response.getContentType();
- verify(response, atLeast(1)).getContentType();
- }
-
- @Test
- public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenOneAssertion() {
- when(response.getContentType()).thenReturn("text/html");
- assertThat(response.getContentType()).isEqualTo("text/html");
- }
+package com.baeldung.servlets;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class UserServletUnitTest {
+
+ private static HttpServletRequest request;
+ private static HttpServletResponse response;
+
+
+ @BeforeClass
+ public static void setUpHttpServletRequestMockInstance() {
+ request = mock(HttpServletRequest.class);
+ }
+
+ @BeforeClass
+ public static void setUpHttpServletResponsetMockInstance() {
+ response = mock(HttpServletResponse.class);
+ }
+
+ @Test
+ public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenCalledAtLeastOnce() {
+ request.getParameter("name");
+ verify(request, atLeast(1)).getParameter("name");
+ }
+
+ @Test
+ public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenOneAssertion() {
+ when(request.getParameter("name")).thenReturn("username");
+ assertThat(request.getParameter("name")).isEqualTo("username");
+ }
+
+ @Test
+ public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenCalledAtLeastOnce() {
+ response.getContentType();
+ verify(response, atLeast(1)).getContentType();
+ }
+
+ @Test
+ public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenOneAssertion() {
+ when(response.getContentType()).thenReturn("text/html");
+ assertThat(response.getContentType()).isEqualTo("text/html");
+ }
}
\ No newline at end of file
diff --git a/libraries/pom.xml b/libraries/pom.xml
index 70346fd799..a7efd55f1d 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -705,6 +705,37 @@
${jctools.version}
+
+
+ io.github.resilience4j
+ resilience4j-circuitbreaker
+ ${resilience4j.version}
+
+
+ io.github.resilience4j
+ resilience4j-ratelimiter
+ ${resilience4j.version}
+
+
+ io.github.resilience4j
+ resilience4j-bulkhead
+ ${resilience4j.version}
+
+
+ io.github.resilience4j
+ resilience4j-retry
+ ${resilience4j.version}
+
+
+ io.github.resilience4j
+ resilience4j-cache
+ ${resilience4j.version}
+
+
+ io.github.resilience4j
+ resilience4j-timelimiter
+ ${resilience4j.version}
+
org.apache.commons
commons-math3
@@ -951,6 +982,7 @@
0.9.4.0006L
2.1.2
2.5.11
+ 0.12.1
3.6.1
3.5.2
3.6
diff --git a/libraries/src/test/java/com/baeldung/resilience4j/Resilience4jUnitTest.java b/libraries/src/test/java/com/baeldung/resilience4j/Resilience4jUnitTest.java
new file mode 100644
index 0000000000..ced95c99cb
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/resilience4j/Resilience4jUnitTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.resilience4j;
+
+import io.github.resilience4j.bulkhead.Bulkhead;
+import io.github.resilience4j.bulkhead.BulkheadConfig;
+import io.github.resilience4j.bulkhead.BulkheadRegistry;
+import io.github.resilience4j.circuitbreaker.CircuitBreaker;
+import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
+import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
+import io.github.resilience4j.retry.Retry;
+import io.github.resilience4j.retry.RetryConfig;
+import io.github.resilience4j.retry.RetryRegistry;
+import io.github.resilience4j.timelimiter.TimeLimiter;
+import io.github.resilience4j.timelimiter.TimeLimiterConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.util.concurrent.*;
+import java.util.function.Function;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+public class Resilience4jUnitTest {
+
+ interface RemoteService {
+
+ int process(int i);
+ }
+
+ private RemoteService service;
+
+ @Before
+ public void setUp() {
+ service = mock(RemoteService.class);
+ }
+
+ @Test
+ public void whenCircuitBreakerIsUsed_thenItWorksAsExpected() {
+ CircuitBreakerConfig config = CircuitBreakerConfig.custom()
+ // Percentage of failures to start short-circuit
+ .failureRateThreshold(20)
+ // Min number of call attempts
+ .ringBufferSizeInClosedState(5)
+ .build();
+ CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
+ CircuitBreaker circuitBreaker = registry.circuitBreaker("my");
+ Function decorated = CircuitBreaker.decorateFunction(circuitBreaker, service::process);
+
+ when(service.process(anyInt())).thenThrow(new RuntimeException());
+
+ for (int i = 0; i < 10; i++) {
+ try {
+ decorated.apply(i);
+ } catch (Exception ignore) {
+ }
+ }
+
+ verify(service, times(5)).process(any(Integer.class));
+ }
+
+ @Test
+ public void whenBulkheadIsUsed_thenItWorksAsExpected() throws InterruptedException {
+ BulkheadConfig config = BulkheadConfig.custom().maxConcurrentCalls(1).build();
+ BulkheadRegistry registry = BulkheadRegistry.of(config);
+ Bulkhead bulkhead = registry.bulkhead("my");
+ Function decorated = Bulkhead.decorateFunction(bulkhead, service::process);
+
+ Future> taskInProgress = callAndBlock(decorated);
+ try {
+ assertThat(bulkhead.isCallPermitted()).isFalse();
+ } finally {
+ taskInProgress.cancel(true);
+ }
+ }
+
+ private Future> callAndBlock(Function decoratedService) throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ when(service.process(anyInt())).thenAnswer(invocation -> {
+ latch.countDown();
+ Thread.currentThread().join();
+ return null;
+ });
+
+ ForkJoinTask> result = ForkJoinPool.commonPool().submit(() -> {
+ decoratedService.apply(1);
+ });
+ latch.await();
+ return result;
+ }
+
+ @Test
+ public void whenRetryIsUsed_thenItWorksAsExpected() {
+ RetryConfig config = RetryConfig.custom().maxAttempts(2).build();
+ RetryRegistry registry = RetryRegistry.of(config);
+ Retry retry = registry.retry("my");
+ Function decorated = Retry.decorateFunction(retry, (Integer s) -> {
+ service.process(s);
+ return null;
+ });
+
+ when(service.process(anyInt())).thenThrow(new RuntimeException());
+ try {
+ decorated.apply(1);
+ fail("Expected an exception to be thrown if all retries failed");
+ } catch (Exception e) {
+ verify(service, times(2)).process(any(Integer.class));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void whenTimeLimiterIsUsed_thenItWorksAsExpected() throws Exception {
+ long ttl = 1;
+ TimeLimiterConfig config = TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(ttl)).build();
+ TimeLimiter timeLimiter = TimeLimiter.of(config);
+
+ Future futureMock = mock(Future.class);
+ Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, () -> futureMock);
+ restrictedCall.call();
+
+ verify(futureMock).get(ttl, TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/meecrowave/pom.xml b/meecrowave/pom.xml
new file mode 100644
index 0000000000..cf13aa1c1b
--- /dev/null
+++ b/meecrowave/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ com.baeldung
+ apache-meecrowave
+ 0.0.1
+ apache-meecrowave
+ A sample REST API application with Meecrowave
+
+
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.meecrowave
+ meecrowave-core
+ 1.2.1
+
+
+
+ org.apache.meecrowave
+ meecrowave-jpa
+ 1.2.1
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 3.10.0
+
+
+ org.apache.meecrowave
+ meecrowave-junit
+ 1.2.0
+ test
+
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+
+
+
+
+ org.apache.meecrowave
+ meecrowave-maven-plugin
+ 1.2.1
+
+
+
+
\ No newline at end of file
diff --git a/meecrowave/src/main/java/com/baeldung/meecrowave/Article.java b/meecrowave/src/main/java/com/baeldung/meecrowave/Article.java
new file mode 100644
index 0000000000..7925e8ff99
--- /dev/null
+++ b/meecrowave/src/main/java/com/baeldung/meecrowave/Article.java
@@ -0,0 +1,30 @@
+package com.baeldung.meecrowave;
+
+public class Article {
+ private String name;
+ private String author;
+
+ public Article() {
+ }
+
+ public Article(String name, String author) {
+ this.author = author;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+}
\ No newline at end of file
diff --git a/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java b/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java
new file mode 100644
index 0000000000..6cb7012c64
--- /dev/null
+++ b/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleEndpoints.java
@@ -0,0 +1,32 @@
+package com.baeldung.meecrowave;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+@RequestScoped
+@Path("article")
+public class ArticleEndpoints {
+
+ @Inject
+ ArticleService articleService;
+
+ @GET
+ public Response getArticle() {
+ return Response.ok()
+ .entity(new Article("name", "author"))
+ .build();
+
+ }
+
+ @POST
+ public Response createArticle(Article article) {
+ return Response.status(Status.CREATED)
+ .entity(articleService.createArticle(article))
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java b/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java
new file mode 100644
index 0000000000..7bd6b87345
--- /dev/null
+++ b/meecrowave/src/main/java/com/baeldung/meecrowave/ArticleService.java
@@ -0,0 +1,10 @@
+package com.baeldung.meecrowave;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ArticleService {
+ public Article createArticle(Article article) {
+ return article;
+ }
+}
diff --git a/meecrowave/src/main/java/com/baeldung/meecrowave/Server.java b/meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
new file mode 100644
index 0000000000..2aa7d0556f
--- /dev/null
+++ b/meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
@@ -0,0 +1,16 @@
+package com.baeldung.meecrowave;
+
+import org.apache.meecrowave.Meecrowave;
+
+public class Server {
+ public static void main(String[] args) {
+ final Meecrowave.Builder builder = new Meecrowave.Builder();
+ builder.setScanningPackageIncludes("com.baeldung.meecrowave");
+ builder.setJaxrsMapping("/api/*");
+ builder.setJsonpPrettify(true);
+
+ try (Meecrowave meecrowave = new Meecrowave(builder)) {
+ meecrowave.bake().await();
+ }
+ }
+}
diff --git a/meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java b/meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
new file mode 100644
index 0000000000..0dc9773490
--- /dev/null
+++ b/meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.meecrowave;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.junit.MonoMeecrowave;
+import org.apache.meecrowave.testing.ConfigurationInject;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+@RunWith(MonoMeecrowave.Runner.class)
+public class ArticleEndpointsTest {
+
+ @ConfigurationInject
+ private Meecrowave.Builder config;
+ private static OkHttpClient client;
+
+ @BeforeClass
+ public static void setup() {
+ client = new OkHttpClient();
+ }
+
+ @Test
+ public void whenRetunedArticle_thenCorrect() throws IOException {
+ final String base = "http://localhost:"+config.getHttpPort();
+
+ Request request = new Request.Builder()
+ .url(base+"/article")
+ .build();
+ Response response = client.newCall(request).execute();
+ assertEquals(200, response.code());
+ }
+}
diff --git a/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java b/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryLiveTest.java
similarity index 99%
rename from persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java
rename to persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryLiveTest.java
index 9eb00b3651..eda9ca15e4 100644
--- a/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java
+++ b/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryLiveTest.java
@@ -16,7 +16,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-public class ArticleRepositoryIntegrationTest {
+public class ArticleRepositoryLiveTest {
private static final String TABLE_NAME = "articles";
diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml
new file mode 100644
index 0000000000..78764f7148
--- /dev/null
+++ b/persistence-modules/java-jpa/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+ ../../pom.xml
+
+ 4.0.0
+
+ java-jpa
+
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+ 5.3.1.Final
+ 1.4.197
+
+
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/Employee.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/Employee.java
new file mode 100644
index 0000000000..bec1b8845a
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/Employee.java
@@ -0,0 +1,43 @@
+package com.baeldung.sqlresultsetmapping;
+
+import javax.persistence.*;
+
+
+@SqlResultSetMapping(
+ name="EmployeeResult",
+ entities={
+ @EntityResult(
+ entityClass = com.baeldung.sqlresultsetmapping.Employee.class,
+ fields={@FieldResult(name="id",column="employeeNumber"),
+ @FieldResult(name="name", column="name")}
+ )
+ }
+)
+@NamedNativeQuery(
+ name="Employees",
+ query="SELECT id as employeeNumber, name FROM EMPLOYEE",
+ resultSetMapping = "EmployeeResult"
+)
+@Entity
+public class Employee {
+
+ @Id
+ private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/ScheduledDay.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/ScheduledDay.java
new file mode 100644
index 0000000000..b72454c506
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/sqlresultsetmapping/ScheduledDay.java
@@ -0,0 +1,80 @@
+package com.baeldung.sqlresultsetmapping;
+
+import javax.persistence.*;
+
+@SqlResultSetMappings(value = {
+ @SqlResultSetMapping(name = "ScheduleResult",
+ classes = { @ConstructorResult(targetClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class,
+ columns = { @ColumnResult(name = "id", type = Long.class),
+ @ColumnResult(name = "employeeId", type = Long.class),
+ @ColumnResult(name = "hourIn"),
+ @ColumnResult(name = "hourOut"),
+ @ColumnResult(name = "dayOfWeek") }) }),
+ @SqlResultSetMapping(name = "FridayEmployeeResult",
+ columns = { @ColumnResult(name = "employeeId") }),
+ @SqlResultSetMapping(name = "EmployeeScheduleResults",
+ entities = { @EntityResult(entityClass = com.baeldung.sqlresultsetmapping.Employee.class),
+ @EntityResult(entityClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class)
+ }) })
+@NamedNativeQuery(name = "FridayEmployees",
+ query = "SELECT employeeId FROM schedule_days WHERE dayOfWeek = 'FRIDAY'",
+ resultSetMapping = "FridayEmployeeResult")
+
+@NamedNativeQuery(name = "Schedules",
+ query = "SELECT * FROM schedule_days WHERE hourIn = 8",
+ resultSetMapping = "ScheduleResult")
+@Entity
+@Table(name = "SCHEDULE_DAYS")
+public class ScheduledDay {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+ private Long employeeId;
+ private Integer hourIn;
+ private Integer hourOut;
+ private String dayOfWeek;
+
+ public ScheduledDay() {
+ }
+
+ public ScheduledDay(Long id, Long employeeId, Integer hourIn, Integer hourOut, String dayofWeek) {
+ this.id = id;
+ this.employeeId = employeeId;
+ this.hourIn = hourIn;
+ this.hourOut = hourOut;
+ this.dayOfWeek = dayofWeek;
+ }
+
+ public Long getEmployeeId() {
+ return employeeId;
+ }
+
+ public void setEmployeeId(Long employeeId) {
+ this.employeeId = employeeId;
+ }
+
+ public Integer getHourIn() {
+ return hourIn;
+ }
+
+ public void setHourIn(Integer hourIn) {
+ this.hourIn = hourIn;
+ }
+
+ public Integer getHourOut() {
+ return hourOut;
+ }
+
+ public void setHourOut(Integer hourOut) {
+ this.hourOut = hourOut;
+ }
+
+ public String getDayOfWeek() {
+ return dayOfWeek;
+ }
+
+ public void setDayOfWeek(String dayOfWeek) {
+ this.dayOfWeek = dayOfWeek;
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..e9230eb6cd
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+ com.baeldung.sqlresultsetmapping.ScheduledDay
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/main/resources/database.sql b/persistence-modules/java-jpa/src/main/resources/database.sql
new file mode 100644
index 0000000000..3310c79a85
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/resources/database.sql
@@ -0,0 +1,19 @@
+CREATE TABLE EMPLOYEE
+(id BIGINT,
+ name VARCHAR(10));
+
+INSERT INTO EMPLOYEE VALUES (1, 'JOHN');
+INSERT INTO EMPLOYEE VALUES (2, 'MARY');
+INSERT INTO EMPLOYEE VALUES (3, 'FRANK');
+
+CREATE TABLE SCHEDULE_DAYS
+(id IDENTITY,
+ employeeId BIGINT,
+ hourIn int,
+ hourOut int,
+ dayOfWeek VARCHAR(10));
+
+INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (1, 13, 21, 'FRIDAY');
+INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (2, 8, 4, 'SATURDAY');
+INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (3, 8, 4, 'MONDAY');
+INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (3, 8, 4, 'FRIDAY');
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/sqlresultsetmapping/SqlResultSetMappingUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/sqlresultsetmapping/SqlResultSetMappingUnitTest.java
new file mode 100644
index 0000000000..7f0cbd3c1d
--- /dev/null
+++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/sqlresultsetmapping/SqlResultSetMappingUnitTest.java
@@ -0,0 +1,71 @@
+package com.baeldung.sqlresultsetmapping;
+
+import static org.junit.Assert.*;
+
+import org.junit.jupiter.api.*;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+import java.util.Collections;
+import java.util.List;
+
+public class SqlResultSetMappingUnitTest {
+
+ private static EntityManager em;
+ private static EntityManagerFactory emFactory;
+
+ @BeforeAll
+ public static void setup() {
+ emFactory = Persistence.createEntityManagerFactory("java-jpa-scheduled-day");
+ em = emFactory.createEntityManager();
+ }
+
+ @Test
+ public void whenNamedQuery_thenColumnResult() {
+ List employeeIds = em.createNamedQuery("FridayEmployees").getResultList();
+ assertEquals(2, employeeIds.size());
+ }
+
+ @Test
+ public void whenNamedQuery_thenConstructorResult() {
+ List scheduleDays = Collections.checkedList(em.createNamedQuery("Schedules", ScheduledDay.class).getResultList(), ScheduledDay.class);
+ assertEquals(3, scheduleDays.size());
+ assertTrue(scheduleDays.stream().allMatch(c -> c.getHourIn().longValue() == 8));
+ }
+
+ @Test
+ public void whenNamedQuery_thenSingleEntityResult() {
+ List employees = Collections.checkedList(em.createNamedQuery("Employees").getResultList(), Employee.class);
+ assertEquals(3, employees.size());
+ assertTrue(employees.stream().allMatch(c -> c.getClass() == Employee.class));
+ }
+
+ @Test
+ public void whenNamedQuery_thenMultipleEntityResult() {
+ final Query query = em.createNativeQuery("SELECT e.id, e.name, d.id, d.employeeId, "
+ + " d.dayOfWeek, d.hourIn, d.hourOut "
+ + " FROM employee e, schedule_days d "
+ + " WHERE e.id = d.employeeId", "EmployeeScheduleResults");
+ List
+
+ com.github.kstyrc
+ embedded-redis
+ ${embedded-redis.version}
+
@@ -79,6 +84,7 @@
2.9.0
0.10.0
2.0.3.RELEASE
+ 0.6
diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
index 4ea8bb4bc0..62a7886f46 100644
--- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
+++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
@@ -1,8 +1,10 @@
package com.baeldung.spring.data.redis.config;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
@@ -18,6 +20,7 @@ import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
@Configuration
@ComponentScan("com.baeldung.spring.data.redis")
@EnableRedisRepositories(basePackages = "com.baeldung.spring.data.redis.repo")
+@PropertySource("classpath:application.properties")
public class RedisConfig {
@Bean
diff --git a/persistence-modules/spring-data-redis/src/main/resources/application.properties b/persistence-modules/spring-data-redis/src/main/resources/application.properties
new file mode 100644
index 0000000000..49886b3b70
--- /dev/null
+++ b/persistence-modules/spring-data-redis/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+spring.redis.host=localhost
+spring.redis.port=6379
\ No newline at end of file
diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java
index 01dbfcff4d..5bc70069c5 100644
--- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java
+++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java
@@ -1,24 +1,44 @@
package com.baeldung.spring.data.redis;
-import com.baeldung.spring.data.redis.config.RedisConfig;
-import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
-import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import java.util.UUID;
-
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.util.UUID;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.baeldung.spring.data.redis.config.RedisConfig;
+import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
+import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RedisConfig.class)
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class RedisMessageListenerIntegrationTest {
+ private static redis.embedded.RedisServer redisServer;
+
@Autowired
private RedisMessagePublisher redisMessagePublisher;
+
+ @BeforeClass
+ public static void startRedisServer() throws IOException {
+ redisServer = new redis.embedded.RedisServer(6379);
+ redisServer.start();
+ }
+
+ @AfterClass
+ public static void stopRedisServer() throws IOException {
+ redisServer.stop();
+ }
@Test
public void testOnMessage() throws Exception {
diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java
index 66ef3c21b2..48832a8de9 100644
--- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java
@@ -3,13 +3,17 @@ package com.baeldung.spring.data.redis.repo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -18,10 +22,24 @@ import com.baeldung.spring.data.redis.model.Student;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RedisConfig.class)
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class StudentRepositoryIntegrationTest {
@Autowired
private StudentRepository studentRepository;
+
+ private static redis.embedded.RedisServer redisServer;
+
+ @BeforeClass
+ public static void startRedisServer() throws IOException {
+ redisServer = new redis.embedded.RedisServer(6379);
+ redisServer.start();
+ }
+
+ @AfterClass
+ public static void stopRedisServer() throws IOException {
+ redisServer.stop();
+ }
@Test
public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception {
diff --git a/persistence-modules/spring-hibernate-3/src/main/resources/exceptionDemoPersistenceConfig.xml b/persistence-modules/spring-hibernate-3/src/main/resources/exceptionDemoPersistenceConfig.xml
index 09314c67b1..263e902e7c 100644
--- a/persistence-modules/spring-hibernate-3/src/main/resources/exceptionDemoPersistenceConfig.xml
+++ b/persistence-modules/spring-hibernate-3/src/main/resources/exceptionDemoPersistenceConfig.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/persistence-modules/spring-hibernate-3/src/main/resources/persistenceConfig.xml b/persistence-modules/spring-hibernate-3/src/main/resources/persistenceConfig.xml
index e7ef9ad765..f39817383b 100644
--- a/persistence-modules/spring-hibernate-3/src/main/resources/persistenceConfig.xml
+++ b/persistence-modules/spring-hibernate-3/src/main/resources/persistenceConfig.xml
@@ -5,7 +5,7 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
>
-
+
diff --git a/pom.xml b/pom.xml
index f875400fc1..d6c440a194 100644
--- a/pom.xml
+++ b/pom.xml
@@ -184,14 +184,12 @@
spring-katharsis
spring-ldap
spring-mockito
- spring-mvc-email
spring-mvc-forms-jsp
spring-mvc-forms-thymeleaf
spring-mvc-java
spring-mvc-velocity
spring-mvc-webflow
spring-mvc-xml
- spring-mvc-simple
spring-mvc-kotlin
spring-security-openid
spring-protobuf
@@ -267,12 +265,13 @@
java-spi
performance-tests
twilio
- spring-boot-ctx-fluent
+ spring-boot-ctx-fluent
java-ee-8-security-api
spring-webflux-amqp
antlr
maven-archetype
maven-java-kotlin
+ apache-meecrowave
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java b/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java
new file mode 100644
index 0000000000..1d3e1b3f8a
--- /dev/null
+++ b/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java
@@ -0,0 +1,59 @@
+package com.baeldung.rxjava;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import rx.Observable;
+import rx.Subscription;
+import rx.observables.ConnectableObservable;
+import rx.subscriptions.Subscriptions;
+
+public class MultipleSubscribersColdObs {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MultipleSubscribersColdObs.class);
+
+ public static void main(String[] args) throws InterruptedException {
+ defaultBehaviour();
+ // subscribeBeforeConnect();
+
+ }
+
+ private static void defaultBehaviour() {
+ Observable obs = getObservable();
+
+ LOGGER.info("Subscribing");
+ Subscription s1 = obs.subscribe(i -> LOGGER.info("subscriber#1 is printing " + i));
+ Subscription s2 = obs.subscribe(i -> LOGGER.info("subscriber#2 is printing " + i));
+
+ s1.unsubscribe();
+ s2.unsubscribe();
+ }
+
+ private static void subscribeBeforeConnect() throws InterruptedException {
+ ConnectableObservable obs = getObservable().publish();
+
+ LOGGER.info("Subscribing");
+ obs.subscribe(i -> LOGGER.info("subscriber #1 is printing " + i));
+ obs.subscribe(i -> LOGGER.info("subscriber #2 is printing " + i));
+ Thread.sleep(1000);
+ LOGGER.info("Connecting");
+ Subscription s = obs.connect();
+ s.unsubscribe();
+
+ }
+
+ private static Observable getObservable() {
+ return Observable.create(subscriber -> {
+ subscriber.onNext(gettingValue(1));
+ subscriber.onNext(gettingValue(2));
+
+ subscriber.add(Subscriptions.create(() -> {
+ LOGGER.info("Clear resources");
+ }));
+ });
+ }
+
+ private static Integer gettingValue(int i) {
+ LOGGER.info("Getting " + i);
+ return i;
+ }
+}
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java b/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java
new file mode 100644
index 0000000000..686c230003
--- /dev/null
+++ b/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java
@@ -0,0 +1,152 @@
+package com.baeldung.rxjava;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JFrame;
+import rx.Observable;
+import rx.Subscription;
+import rx.observables.ConnectableObservable;
+import rx.subscriptions.Subscriptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultipleSubscribersHotObs {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MultipleSubscribersHotObs.class);
+ private static JFrame frame;
+
+ public static void main(String[] args) throws InterruptedException, InvocationTargetException {
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ createAndShowGUI();
+ }
+ });
+
+ defaultBehaviour();
+ // subscribeBeforeConnect();
+ // connectBeforeSubscribe();
+ // autoConnectAndSubscribe();
+ // refCountAndSubscribe();
+ }
+
+ private static void createAndShowGUI() {
+ frame = new JFrame("Hot Observable Demo");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().setBackground(Color.GRAY);
+ frame.setPreferredSize(new Dimension(500, 500));
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public static void defaultBehaviour() throws InterruptedException {
+ Observable obs = getObservable();
+
+ LOGGER.info("subscribing #1");
+ Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
+
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #2");
+ Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe#1");
+ subscription1.unsubscribe();
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe#2");
+ subscription2.unsubscribe();
+ }
+
+ public static void subscribeBeforeConnect() throws InterruptedException {
+
+ ConnectableObservable obs = getObservable().publish();
+
+ LOGGER.info("subscribing #1");
+ Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #2");
+ Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("connecting:");
+ Subscription s = obs.connect();
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe connected");
+ s.unsubscribe();
+
+ }
+
+ public static void connectBeforeSubscribe() throws InterruptedException {
+
+ ConnectableObservable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish();
+ LOGGER.info("connecting:");
+ Subscription s = obs.connect();
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #1");
+ obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #2");
+ obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ s.unsubscribe();
+
+ }
+
+ public static void autoConnectAndSubscribe() throws InterruptedException {
+ Observable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish().autoConnect();
+
+ LOGGER.info("autoconnect()");
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #1");
+ Subscription s1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #2");
+ Subscription s2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
+
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe 1");
+ s1.unsubscribe();
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe 2");
+ s2.unsubscribe();
+ }
+
+ public static void refCountAndSubscribe() throws InterruptedException {
+ Observable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish().refCount();
+
+ LOGGER.info("refcount()");
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #1");
+ Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
+ Thread.sleep(1000);
+ LOGGER.info("subscribing #2");
+ Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
+
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe#1");
+ subscription1.unsubscribe();
+ Thread.sleep(1000);
+ LOGGER.info("unsubscribe#2");
+ subscription2.unsubscribe();
+
+ }
+
+ private static Observable getObservable() {
+ return Observable.create(subscriber -> {
+ frame.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ subscriber.onNext(e.getX());
+ }
+ });
+ subscriber.add(Subscriptions.create(() -> {
+ LOGGER.info("Clear resources");
+ for (MouseListener listener : frame.getListeners(MouseListener.class)) {
+ frame.removeMouseListener(listener);
+ }
+ }));
+ });
+ }
+}
diff --git a/spring-5-mvc/src/main/java/com/baeldung/Constants.java b/spring-5-mvc/src/main/java/com/baeldung/Constants.java
new file mode 100644
index 0000000000..472f3280b7
--- /dev/null
+++ b/spring-5-mvc/src/main/java/com/baeldung/Constants.java
@@ -0,0 +1,21 @@
+package com.baeldung;
+
+public class Constants {
+
+ public static final String GENERIC_EXCEPTION = "Exception encountered!";
+
+ /**
+ * API endpoints.
+ */
+ public static final String API_RBE = "/rbe";
+ public static final String API_SSE = "/sse";
+ public static final String API_SRB = "/srb";
+
+ /**
+ * API Responses.
+ */
+ public static final String API_RBE_MSG = "I Was Sent From a Response Body Emitter!";
+ public static final String API_SSE_MSG = "I Was Sent From a Sse!";
+ public static final String API_SRB_MSG = "I Was Sent From a Streaming Response Body!";
+
+}
diff --git a/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java b/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java
index a9ffee14da..b06f50b742 100644
--- a/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java
+++ b/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java
@@ -49,8 +49,6 @@ public class Foo {
this.name = name;
}
- //
-
@Override
public int hashCode() {
final int prime = 31;
diff --git a/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java b/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java
index cf78977961..fa07555bba 100644
--- a/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java
+++ b/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java
@@ -16,8 +16,6 @@ public class DataSetupBean implements InitializingBean {
@Autowired
private FooRepository repo;
- //
-
@Override
public void afterPropertiesSet() throws Exception {
IntStream.range(1, 5).forEach(i -> repo.save(new Foo(randomAlphabetic(8))));
diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java b/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java
new file mode 100644
index 0000000000..4af8eb9bd3
--- /dev/null
+++ b/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java
@@ -0,0 +1,35 @@
+package com.baeldung.web;
+
+import com.baeldung.Constants;
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
+
+@Controller
+public class ResponseBodyEmitterController {
+
+ @GetMapping(Constants.API_RBE)
+ public ResponseEntity handleRbe() {
+ ResponseBodyEmitter emitter = new ResponseBodyEmitter();
+ ExecutorService nonBlockingService = Executors.newSingleThreadExecutor();
+
+ nonBlockingService.execute(() -> {
+ try {
+ emitter.send(Constants.API_RBE_MSG + " @ " + new Date(), MediaType.TEXT_PLAIN);
+ emitter.complete();
+ } catch (Exception ex) {
+ System.out.println(Constants.GENERIC_EXCEPTION);
+ emitter.completeWithError(ex);
+ }
+ });
+
+ return new ResponseEntity(emitter, HttpStatus.OK);
+ }
+
+}
diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java b/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java
new file mode 100644
index 0000000000..390178aaef
--- /dev/null
+++ b/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java
@@ -0,0 +1,32 @@
+package com.baeldung.web;
+
+import com.baeldung.Constants;
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+@Controller
+public class SseEmitterController {
+
+ @GetMapping(Constants.API_SSE)
+ public SseEmitter handleSse() {
+ SseEmitter emitter = new SseEmitter();
+
+ ExecutorService nonBlockingService = Executors.newSingleThreadExecutor();
+ nonBlockingService.execute(() -> {
+ try {
+ emitter.send(Constants.API_SSE_MSG + " @ " + new Date());
+ emitter.complete();
+ } catch (Exception ex) {
+ System.out.println(Constants.GENERIC_EXCEPTION);
+ emitter.completeWithError(ex);
+ }
+ });
+
+ return emitter;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java b/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java
new file mode 100644
index 0000000000..1722ad85cd
--- /dev/null
+++ b/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java
@@ -0,0 +1,23 @@
+package com.baeldung.web;
+
+import com.baeldung.Constants;
+import java.util.Date;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+@Controller
+public class StreamingResponseBodyController {
+
+ @GetMapping(Constants.API_SRB)
+ public ResponseEntity handleRbe() {
+ StreamingResponseBody stream = out -> {
+ String msg = Constants.API_SRB_MSG + " @ " + new Date();
+ out.write(msg.getBytes());
+ };
+ return new ResponseEntity(stream, HttpStatus.OK);
+ }
+
+}
diff --git a/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp
new file mode 100644
index 0000000000..df5baf7adb
--- /dev/null
+++ b/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp
@@ -0,0 +1,86 @@
+<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
+<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
+
+
+
+
+
+
+ Spring MVC Async
+ " rel="stylesheet">
+
+
+
+ Spring MVC Async
+
+
+
+
+
+
+
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java
new file mode 100644
index 0000000000..a50651ced7
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorAttributes.java
@@ -0,0 +1,55 @@
+
+package com.baeldung.reactive.errorhandling;
+
+import java.util.Map;
+import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+
+@Component
+public class GlobalErrorAttributes extends DefaultErrorAttributes{
+
+ private HttpStatus status = HttpStatus.BAD_REQUEST;
+ private String message = "please provide a name";
+
+ public GlobalErrorAttributes() {
+ super(false);
+ }
+
+ @Override
+ public Map getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
+ Map map = super.getErrorAttributes(request, includeStackTrace);
+ map.put("status", getStatus());
+ map.put("message", getMessage());
+ return map;
+ }
+
+ /**
+ * @return the status
+ */
+ public HttpStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * @param status the status to set
+ */
+ public void setStatus(HttpStatus status) {
+ this.status = status;
+ }
+
+ /**
+ * @return the message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * @param message the message to set
+ */
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java
new file mode 100644
index 0000000000..09bccb0d5e
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java
@@ -0,0 +1,47 @@
+
+package com.baeldung.reactive.errorhandling;
+
+import java.util.Map;
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+@Order(-2)
+public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
+
+ public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext,
+ ServerCodecConfigurer serverCodecConfigurer) {
+ super(g, new ResourceProperties(), applicationContext);
+ super.setMessageWriters(serverCodecConfigurer.getWriters());
+ super.setMessageReaders(serverCodecConfigurer.getReaders());
+ }
+
+ @Override
+ protected RouterFunction getRoutingFunction(final ErrorAttributes errorAttributes) {
+ return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
+ }
+
+ private Mono renderErrorResponse(final ServerRequest request) {
+
+ final Map errorPropertiesMap = getErrorAttributes(request, false);
+
+ return ServerResponse.status(HttpStatus.BAD_REQUEST)
+ .contentType(MediaType.APPLICATION_JSON_UTF8)
+ .body(BodyInserters.fromObject(errorPropertiesMap));
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java
new file mode 100644
index 0000000000..38d35544a7
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/NameRequiredException.java
@@ -0,0 +1,12 @@
+
+package com.baeldung.reactive.errorhandling;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ResponseStatusException;
+
+public class NameRequiredException extends ResponseStatusException {
+
+ public NameRequiredException(HttpStatus status, String message, Throwable e) {
+ super(status, message, e);
+ }
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java
new file mode 100644
index 0000000000..87b78a4654
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java
@@ -0,0 +1,29 @@
+
+package com.baeldung.reactive.errorhandling.handlers;
+
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+public class Handler1 {
+
+ public Mono handleRequest1(ServerRequest request) {
+ return sayHello(request).onErrorReturn("Hello, Stranger")
+ .flatMap(s -> ServerResponse.ok()
+ .contentType(MediaType.TEXT_PLAIN)
+ .syncBody(s));
+ }
+
+ private Mono sayHello(ServerRequest request) {
+ try {
+ return Mono.just("Hello, " + request.queryParam("name")
+ .get());
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java
new file mode 100644
index 0000000000..12172a0f54
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java
@@ -0,0 +1,38 @@
+
+package com.baeldung.reactive.errorhandling.handlers;
+
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+public class Handler2 {
+
+public Mono handleRequest2(ServerRequest request) {
+ return
+ sayHello(request)
+ .flatMap(s -> ServerResponse.ok()
+ .contentType(MediaType.TEXT_PLAIN)
+ .syncBody(s))
+ .onErrorResume(e -> sayHelloFallback()
+ .flatMap(s -> ServerResponse.ok()
+ .contentType(MediaType.TEXT_PLAIN)
+ .syncBody(s)));
+}
+
+ private Mono sayHello(ServerRequest request) {
+ try {
+ return Mono.just("Hello, " + request.queryParam("name")
+ .get());
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+ }
+
+ private Mono sayHelloFallback() {
+ return Mono.just("Hello, Stranger");
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java
new file mode 100644
index 0000000000..e95b039cce
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java
@@ -0,0 +1,34 @@
+
+package com.baeldung.reactive.errorhandling.handlers;
+
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+public class Handler3 {
+
+ public Mono handleRequest3(ServerRequest request) {
+ return
+ sayHello(request)
+ .flatMap(s -> ServerResponse.ok()
+ .contentType(MediaType.TEXT_PLAIN)
+ .syncBody(s))
+ .onErrorResume(e -> (Mono.just("Hi, I looked around for your name but found: " +
+ e.getMessage())).flatMap(s -> ServerResponse.ok()
+ .contentType(MediaType.TEXT_PLAIN)
+ .syncBody(s)));
+ }
+
+ private Mono sayHello(ServerRequest request) {
+ try {
+ return Mono.just("Hello, " + request.queryParam("name")
+ .get());
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java
new file mode 100644
index 0000000000..3d6ef258d3
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler4.java
@@ -0,0 +1,30 @@
+
+package com.baeldung.reactive.errorhandling.handlers;
+
+import com.baeldung.reactive.errorhandling.NameRequiredException;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+public class Handler4 {
+
+public Mono handleRequest4(ServerRequest request) {
+ return ServerResponse.ok()
+ .body(sayHello(request)
+ .onErrorResume(e ->
+ Mono.error(new NameRequiredException(
+ HttpStatus.BAD_REQUEST, "please provide a name", e))), String.class);
+}
+
+ private Mono sayHello(ServerRequest request) {
+ try {
+ return Mono.just("Hello, " + request.queryParam("name").get());
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java
new file mode 100644
index 0000000000..41605b355b
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler5.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.handlers;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+@Component
+public class Handler5 {
+
+ public Mono handleRequest5(ServerRequest request) {
+ return ServerResponse.ok()
+ .body(sayHello(request), String.class);
+
+ }
+
+ private Mono sayHello(ServerRequest request) {
+ return Mono.just("Hello, " + request.queryParam("name").get());
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java
new file mode 100644
index 0000000000..91be24571c
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router1.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.routers;
+
+import com.baeldung.reactive.errorhandling.handlers.Handler1;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Component
+public class Router1 {
+
+ @Bean
+ public RouterFunction routeRequest1(Handler1 handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/api/endpoint1")
+ .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest1);
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java
new file mode 100644
index 0000000000..bc7831f494
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router2.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.routers;
+
+import com.baeldung.reactive.errorhandling.handlers.Handler2;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Component
+public class Router2 {
+
+ @Bean
+ public RouterFunction routeRequest2(Handler2 handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/api/endpoint2")
+ .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest2);
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java
new file mode 100644
index 0000000000..461e6fe9e7
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router3.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.routers;
+
+import com.baeldung.reactive.errorhandling.handlers.Handler3;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Component
+public class Router3 {
+
+ @Bean
+ public RouterFunction routeRequest3(Handler3 handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/api/endpoint3")
+ .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest3);
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java
new file mode 100644
index 0000000000..9dccc6858f
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router4.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.routers;
+
+import com.baeldung.reactive.errorhandling.handlers.Handler4;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Component
+public class Router4 {
+
+ @Bean
+ public RouterFunction routeRequest4(Handler4 handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/api/endpoint4")
+ .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest4);
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java
new file mode 100644
index 0000000000..59fd587fc8
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/routers/Router5.java
@@ -0,0 +1,22 @@
+
+package com.baeldung.reactive.errorhandling.routers;
+
+import com.baeldung.reactive.errorhandling.handlers.Handler5;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+@Component
+public class Router5 {
+
+ @Bean
+ public RouterFunction routeRequest5(Handler5 handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/api/endpoint5")
+ .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest5);
+ }
+
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/controllers/ResponseHeaderController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/controllers/ResponseHeaderController.java
new file mode 100644
index 0000000000..5220ea2f4c
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/controllers/ResponseHeaderController.java
@@ -0,0 +1,35 @@
+package com.baeldung.reactive.responseheaders.controllers;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("/response-header")
+public class ResponseHeaderController {
+
+ @GetMapping("/response-entity")
+ public Mono> usingResponseEntityBuilder() {
+ String responseHeaderKey = "Baeldung-Example-Header";
+ String responseHeaderValue = "Value-ResponseEntityBuilder";
+ String responseBody = "Response with header using ResponseEntity (builder)";
+
+ return Mono.just(ResponseEntity.ok()
+ .header(responseHeaderKey, responseHeaderValue)
+ .body(responseBody));
+ }
+
+ @GetMapping("/server-http-response")
+ public Mono usingServerHttpResponse(ServerHttpResponse response) {
+ String responseHeaderKey = "Baeldung-Example-Header";
+ String responseHeaderValue = "Value-ServerHttpResponse";
+ String responseBody = "Response with header using ServerHttpResponse";
+
+ response.getHeaders().add(responseHeaderKey, responseHeaderValue);
+ return Mono.just(responseBody);
+ }
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/filter/AddResponseHeaderWebFilter.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/filter/AddResponseHeaderWebFilter.java
new file mode 100644
index 0000000000..8d8484f5cd
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/filter/AddResponseHeaderWebFilter.java
@@ -0,0 +1,20 @@
+package com.baeldung.reactive.responseheaders.filter;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+
+import reactor.core.publisher.Mono;
+
+@Component
+public class AddResponseHeaderWebFilter implements WebFilter {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
+ exchange.getResponse()
+ .getHeaders()
+ .add("Baeldung-Example-Filter-Header", "Value-Filter");
+ return chain.filter(exchange);
+ }
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/handlers/ResponseHeaderHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/handlers/ResponseHeaderHandler.java
new file mode 100644
index 0000000000..20f76d3b6e
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/handlers/ResponseHeaderHandler.java
@@ -0,0 +1,21 @@
+package com.baeldung.reactive.responseheaders.functional.handlers;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+import reactor.core.publisher.Mono;
+
+@Component
+public class ResponseHeaderHandler {
+
+ public Mono useHandler(final ServerRequest request) {
+ String responseHeaderKey = "Baeldung-Example-Header";
+ String responseHeaderValue = "Value-Handler";
+ String responseBody = "Response with header using Handler";
+
+ return ServerResponse.ok()
+ .header(responseHeaderKey, responseHeaderValue)
+ .body(Mono.just(responseBody),String.class);
+ }
+}
diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/routers/ResponseHeadersRouterFunctions.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/routers/ResponseHeadersRouterFunctions.java
new file mode 100644
index 0000000000..63f7c7f036
--- /dev/null
+++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/responseheaders/functional/routers/ResponseHeadersRouterFunctions.java
@@ -0,0 +1,20 @@
+package com.baeldung.reactive.responseheaders.functional.routers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+import com.baeldung.reactive.responseheaders.functional.handlers.ResponseHeaderHandler;
+
+@Configuration
+public class ResponseHeadersRouterFunctions {
+
+ @Bean
+ public RouterFunction responseHeaderRoute(@Autowired ResponseHeaderHandler handler) {
+ return RouterFunctions.route(RequestPredicates.GET("/functional-response-header/single-handler"), handler::useHandler);
+ }
+}
diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java
new file mode 100644
index 0000000000..bea2eaa75f
--- /dev/null
+++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java
@@ -0,0 +1,168 @@
+package com.baeldung.reactive.errorhandling;
+
+import java.io.IOException;
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
+public class ErrorHandlingIntegrationTest {
+
+ @Autowired
+ private WebTestClient webTestClient;
+
+ @Test
+ public void givenErrorReturn_whenUsernamePresent_thenOk() throws IOException {
+
+ String s = webTestClient.get()
+ .uri("/api/endpoint1?name={username}", "Tony")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Tony", s);
+
+ }
+
+ @Test
+ public void givenErrorReturn_whenNoUsername_thenOk() throws IOException {
+
+ String s = webTestClient.get()
+ .uri("/api/endpoint1")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Stranger", s);
+ }
+
+ @Test
+ public void givenResumeFallback_whenUsernamePresent_thenOk() throws IOException {
+
+ String s = webTestClient.get()
+ .uri("/api/endpoint2?name={username}", "Tony")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Tony", s);
+ }
+
+ @Test
+ public void givenResumeFallback_whenNoUsername_thenOk() throws IOException {
+ String s = webTestClient.get()
+ .uri("/api/endpoint2")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Stranger", s);
+
+ }
+
+ @Test
+ public void givenResumeDynamicValue_whenUsernamePresent_thenOk() throws IOException {
+
+ String s = webTestClient.get()
+ .uri("/api/endpoint3?name={username}", "Tony")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Tony", s);
+ }
+
+ @Test
+ public void givenResumeDynamicValue_whenNoUsername_thenOk() throws IOException {
+ String s = webTestClient.get()
+ .uri("/api/endpoint3")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hi, I looked around for your name but found: No value present", s);
+ }
+
+ @Test
+ public void givenResumeRethrow_whenUsernamePresent_thenOk() throws IOException {
+ String s = webTestClient.get()
+ .uri("/api/endpoint4?name={username}", "Tony")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Tony", s);
+ }
+
+ @Test
+ public void givenResumeRethrow_whenNoUsername_thenOk() throws IOException {
+
+ webTestClient.get()
+ .uri("/api/endpoint4")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .expectStatus()
+ .isBadRequest()
+ .expectHeader()
+ .contentType(MediaType.APPLICATION_JSON_UTF8)
+ .expectBody()
+ .jsonPath("$.message")
+ .isNotEmpty()
+ .jsonPath("$.message")
+ .isEqualTo("please provide a name");
+ }
+
+ @Test
+ public void givenGlobalErrorHandling_whenUsernamePresent_thenOk() throws IOException {
+
+ String s = webTestClient.get()
+ .uri("/api/endpoint5?name={username}", "Tony")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertEquals("Hello, Tony", s);
+ }
+
+ @Test
+ public void givenGlobalErrorHandling_whenNoUsername_thenOk() throws IOException {
+ webTestClient.get()
+ .uri("/api/endpoint5")
+ .accept(MediaType.TEXT_PLAIN)
+ .exchange()
+ .expectStatus()
+ .isBadRequest()
+ .expectHeader()
+ .contentType(MediaType.APPLICATION_JSON_UTF8)
+ .expectBody()
+ .jsonPath("$.message")
+ .isNotEmpty()
+ .jsonPath("$.message")
+ .isEqualTo("please provide a name");
+
+ }
+
+}
diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/responseheaders/ResponseHeaderLiveTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/responseheaders/ResponseHeaderLiveTest.java
new file mode 100644
index 0000000000..db563e27d1
--- /dev/null
+++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/responseheaders/ResponseHeaderLiveTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.reactive.responseheaders;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class ResponseHeaderLiveTest {
+
+ private static final String BASE_URL = "http://localhost:8080";
+ private static final String ANNOTATION_BASE_URL = BASE_URL + "/response-header";
+ private static final String FUNCTIONAL_BASE_URL = BASE_URL + "/functional-response-header";
+ private static final String SERVICE_SINGLE_RESPONSE_HEADER = "Baeldung-Example-Header";
+ private static final String SERVICE_FILTER_RESPONSE_HEADER = "Baeldung-Example-Filter-Header";
+ private static final String SERVICE_FILTER_RESPONSE_HEADER_VALUE = "Value-Filter";
+
+ private static WebTestClient client;
+
+ @BeforeAll
+ public static void setup() {
+ client = WebTestClient.bindToServer()
+ .baseUrl(BASE_URL)
+ .build();
+ }
+
+ @Test
+ public void whenUsingResponseEntityBuilderRequest_thenObtainResponseWithCorrectHeaders() {
+ client = WebTestClient.bindToServer()
+ .baseUrl(BASE_URL)
+ .build();
+ ResponseSpec response = client.get()
+ .uri(ANNOTATION_BASE_URL + "/response-entity")
+ .exchange();
+
+ response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ResponseEntityBuilder")
+ .expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
+ }
+
+ @Test
+ public void whenUsingServerHttpResponseRequest_thenObtainResponseWithCorrectHeaders() {
+ ResponseSpec response = client.get()
+ .uri(ANNOTATION_BASE_URL + "/server-http-response")
+ .exchange();
+
+ response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ServerHttpResponse")
+ .expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
+ }
+
+ @Test
+ public void whenUsingFunctionalHandlerRequest_thenObtainResponseWithCorrectHeaders() {
+ ResponseSpec response = client.get()
+ .uri(FUNCTIONAL_BASE_URL + "/single-handler")
+ .exchange();
+
+ response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-Handler")
+ .expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
+ }
+}
diff --git a/spring-batch/src/main/java/org/baeldung/batchscheduler/SpringBatchScheduler.java b/spring-batch/src/main/java/org/baeldung/batchscheduler/SpringBatchScheduler.java
new file mode 100644
index 0000000000..edb9b7cfa5
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/batchscheduler/SpringBatchScheduler.java
@@ -0,0 +1,172 @@
+package org.baeldung.batchscheduler;
+
+import java.util.Date;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.baeldung.batchscheduler.model.Book;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.launch.support.SimpleJobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
+import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
+import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.support.ScheduledMethodRunnable;
+
+@Configuration
+@EnableBatchProcessing
+@EnableScheduling
+public class SpringBatchScheduler {
+
+ private final Logger logger = LoggerFactory.getLogger(SpringBatchScheduler.class);
+
+ private AtomicBoolean enabled = new AtomicBoolean(true);
+
+ private Date currentLaunchDate;
+
+ private final Map
@@ -73,6 +79,7 @@
UTF-8
1.8
2.17
+ 2.0.0
diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
index 092ebb93fd..477a7d2adb 100644
--- a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
+++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertNotEquals;
@RunWith(SpringJUnit4ClassRunner.class)
-@SpringBootTest
+@SpringBootTest(classes = {SpringJenkinsPipelineApplication.class, TestMongoConfig.class })
public class SomeIntegrationTest {
@Autowired
private StudentRepository studentRepository;
diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java
new file mode 100644
index 0000000000..a85491cf7e
--- /dev/null
+++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java
@@ -0,0 +1,11 @@
+package com.baeldung;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
+public class TestMongoConfig {
+
+}
\ No newline at end of file
diff --git a/spring-jooq/pom.xml b/spring-jooq/pom.xml
index bd8bc6f404..a2ca229031 100644
--- a/spring-jooq/pom.xml
+++ b/spring-jooq/pom.xml
@@ -5,9 +5,10 @@
0.0.1-SNAPSHOT
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.4.RELEASE
+
@@ -55,6 +56,10 @@
org.springframework.boot
spring-boot-starter-jooq
+
+ org.springframework.boot
+ spring-boot-starter-test
+
diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java b/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java
index 25317309ee..5e76fb3c93 100644
--- a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java
+++ b/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java
@@ -12,14 +12,16 @@ import org.jooq.impl.DSL;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
-import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = Application.class)
-@Transactional("transactionManager")
+import com.baeldung.jooq.introduction.PersistenceContextIntegrationTest;
+
+@ContextConfiguration(classes = PersistenceContextIntegrationTest.class)
+@Transactional(transactionManager = "transactionManager")
+@RunWith(SpringJUnit4ClassRunner.class)
public class SpringBootIntegrationTest {
@Autowired
diff --git a/spring-mvc-email/README.md b/spring-mvc-email/README.md
deleted file mode 100644
index aa880188d7..0000000000
--- a/spring-mvc-email/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## Relevant articles:
-
-- [Guide to Spring Email](http://www.baeldung.com/spring-email)
-
-## Spring MVC Email
-
-Example Spring MVC project to send email from web form.
-
-### Installing and Running
-
-Just run the Spring Boot application.
-Type http://localhost:8080 in your browser to open the application.
-
-
-### Sending test emails
-
-Follow UI links to send simple email, email using template or email with attachment.
diff --git a/spring-mvc-email/pom.xml b/spring-mvc-email/pom.xml
deleted file mode 100644
index 40d83046ef..0000000000
--- a/spring-mvc-email/pom.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
- 4.0.0
-
- org.baeldung.spring
- spring-mvc-email
- 1.0
- spring-mvc-email
- war
-
-
- parent-boot-1
- com.baeldung
- 0.0.1-SNAPSHOT
- ../parent-boot-1
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-tomcat
-
-
-
- org.springframework.boot
- spring-boot-starter-mail
-
-
-
- javax.servlet
- jstl
-
-
-
-
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java b/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java
deleted file mode 100644
index bc5d6b3151..0000000000
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.baeldung.spring;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
-
-
-@SpringBootApplication
-public class Application extends SpringBootServletInitializer {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
-}
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java b/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java
deleted file mode 100644
index 9078d44764..0000000000
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.baeldung.spring.app.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.mail.SimpleMailMessage;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-import org.springframework.web.servlet.view.InternalResourceViewResolver;
-import org.springframework.web.servlet.view.JstlView;
-import org.springframework.web.servlet.view.UrlBasedViewResolver;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Olga
- */
-@Configuration
-@ComponentScan("com.baeldung.spring")
-@EnableWebMvc //tha same as
-public class AppConfig extends WebMvcConfigurerAdapter {
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
- }
-
- @Bean
- public UrlBasedViewResolver urlBasedViewResolver() {
- UrlBasedViewResolver resolver = new UrlBasedViewResolver();
- resolver.setOrder(0);
- resolver.setPrefix("/WEB-INF/views/");
- resolver.setSuffix(".jsp");
- resolver.setCache(false);
- resolver.setViewClass(JstlView.class);
- return resolver;
- }
-
- @Bean
- public InternalResourceViewResolver internalResourceViewResolver() {
- InternalResourceViewResolver resolver = new InternalResourceViewResolver();
- resolver.setOrder(1);
- resolver.setPrefix("/WEB-INF/views/");
- resolver.setSuffix(".jsp");
- resolver.setViewClass(JstlView.class);
- return resolver;
- }
-
- @Bean
- public SimpleMailMessage templateSimpleMessage() {
- SimpleMailMessage message = new SimpleMailMessage();
- message.setText("This is the test email template for your email:\n%s\n");
- return message;
- }
-}
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java b/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java
deleted file mode 100644
index 656e237a9e..0000000000
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.baeldung.spring.controllers;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Olga
- */
-@Controller
-@RequestMapping({"/","/home"})
-public class HomeController {
-
- @RequestMapping(method = RequestMethod.GET)
- public String showHomePage() {
- return "home";
- }
-}
diff --git a/spring-mvc-email/src/main/resources/META-INF/application.xml b/spring-mvc-email/src/main/resources/META-INF/application.xml
deleted file mode 100644
index 759a312bd4..0000000000
--- a/spring-mvc-email/src/main/resources/META-INF/application.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
- SpringMVCEmail.war
- SpringMVCEmail
-
-
-
-
- web.war
- SpringMVCEmailWeb
-
-
-
\ No newline at end of file
diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/web.xml b/spring-mvc-email/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 4cd41216d9..0000000000
--- a/spring-mvc-email/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- simpleweb
- org.springframework.web.servlet.DispatcherServlet
-
- contextClass
-
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
-
- contextConfigLocation
- com.baeldung.spring.app.config.AppConfig
-
- 1
-
-
-
- simpleweb
- /
-
-
-
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/WebsocketSendToUserController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/WebsocketSendToUserController.java
index d4c15aead9..4b55bcc00f 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/WebsocketSendToUserController.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/WebsocketSendToUserController.java
@@ -1,23 +1,19 @@
package com.baeldung.web.controller;
-import com.google.gson.Gson;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
-import org.springframework.messaging.handler.annotation.MessageMapping;
-import org.springframework.messaging.handler.annotation.Payload;
-import org.springframework.messaging.simp.SimpMessageSendingOperations;
-import org.springframework.messaging.simp.annotation.SendToUser;
-import org.springframework.stereotype.Controller;
-
import java.security.Principal;
import java.util.Map;
+import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
+import org.springframework.messaging.handler.annotation.MessageMapping;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.messaging.simp.annotation.SendToUser;
+import org.springframework.stereotype.Controller;
+
+import com.google.gson.Gson;
+
@Controller
public class WebsocketSendToUserController {
- @Autowired
- private SimpMessageSendingOperations messagingTemplate;
-
private Gson gson = new Gson();
@MessageMapping("/message")
diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md
index 3505fb8009..39053534fa 100644
--- a/spring-mvc-simple/README.md
+++ b/spring-mvc-simple/README.md
@@ -5,3 +5,4 @@
- [Spring 5 and Servlet 4 – The PushBuilder](http://www.baeldung.com/spring-5-push)
- [Servlet Redirect vs Forward](http://www.baeldung.com/servlet-redirect-forward)
- [Apache Tiles Integration with Spring MVC](http://www.baeldung.com/spring-mvc-apache-tiles)
+- [Guide to Spring Email](http://www.baeldung.com/spring-email)
diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml
index 08eab59540..ac112f7e29 100644
--- a/spring-mvc-simple/pom.xml
+++ b/spring-mvc-simple/pom.xml
@@ -20,6 +20,15 @@
spring-oxm
${spring-oxm.version}
+
+ org.springframework
+ spring-context-support
+
+
+ com.sun.mail
+ javax.mail
+ 1.6.1
+
javax.servlet
javax.servlet-api
@@ -122,6 +131,14 @@
json
${json.version}
+
+ org.apache.maven.surefire
+ surefire-logger-api
+ ${maven-surefire-plugin.version}
+
+ test
+ true
+
@@ -171,7 +188,7 @@
1.2
2.3.2-b02
4.0.0
- 5.4.1.Final
+ 6.0.10.Final
enter-location-of-server
1.3.2
1.8
diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java
index c28ee02eef..284be6c212 100644
--- a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java
+++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java
@@ -8,6 +8,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@@ -20,10 +23,11 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver;
import java.util.ArrayList;
import java.util.List;
+import java.util.Properties;
@Configuration
@EnableWebMvc
-@ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator" })
+@ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator", "com.baeldung.spring.mail" })
public class ApplicationConfiguration implements WebMvcConfigurer {
@Override
@@ -60,4 +64,29 @@ public class ApplicationConfiguration implements WebMvcConfigurer {
converters.add(new RssChannelHttpMessageConverter());
converters.add(new JsonChannelHttpMessageConverter());
}
+
+ @Bean
+ public SimpleMailMessage templateSimpleMessage() {
+ SimpleMailMessage message = new SimpleMailMessage();
+ message.setText("This is the test email template for your email:\n%s\n");
+ return message;
+ }
+
+ @Bean
+ public JavaMailSender getJavaMailSender() {
+ JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+ mailSender.setHost("smtp.gmail.com");
+ mailSender.setPort(587);
+
+ mailSender.setUsername("my.gmail@gmail.com");
+ mailSender.setPassword("password");
+
+ Properties props = mailSender.getJavaMailProperties();
+ props.put("mail.transport.protocol", "smtp");
+ props.put("mail.smtp.auth", "true");
+ props.put("mail.smtp.starttls.enable", "true");
+ props.put("mail.debug", "true");
+
+ return mailSender;
+ }
}
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/MailController.java
similarity index 95%
rename from spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java
rename to spring-mvc-simple/src/main/java/com/baeldung/spring/controller/MailController.java
index ff828ca9ec..16d1202eef 100644
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java
+++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/MailController.java
@@ -1,9 +1,8 @@
-package com.baeldung.spring.controllers;
+package com.baeldung.spring.controller;
import com.baeldung.spring.mail.EmailServiceImpl;
-import com.baeldung.spring.web.dto.MailObject;
+import com.baeldung.spring.domain.MailObject;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
@@ -62,6 +61,11 @@ public class MailController {
props.put("additionalInfo", "To make sure that you send an attachment with this email, change the value for the 'attachment.invoice' in the application.properties file to the path to the attachment.");
labels.put("sendAttachment", props);
}
+
+ @RequestMapping(method = RequestMethod.GET)
+ public String showEmailsPage() {
+ return "emails";
+ }
@RequestMapping(value = {"/send", "/sendTemplate", "/sendAttachment"}, method = RequestMethod.GET)
public String createMail(Model model,
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/domain/MailObject.java
similarity index 89%
rename from spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java
rename to spring-mvc-simple/src/main/java/com/baeldung/spring/domain/MailObject.java
index 9623ff5d78..aceaf685fa 100644
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java
+++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/domain/MailObject.java
@@ -1,7 +1,6 @@
-package com.baeldung.spring.web.dto;
-
-import org.hibernate.validator.constraints.Email;
+package com.baeldung.spring.domain;
+import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailService.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/mail/EmailService.java
similarity index 100%
rename from spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailService.java
rename to spring-mvc-simple/src/main/java/com/baeldung/spring/mail/EmailService.java
diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java
similarity index 99%
rename from spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java
rename to spring-mvc-simple/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java
index ca418a7d90..039b970d8e 100644
--- a/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java
+++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java
@@ -8,9 +8,10 @@ import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
+import java.io.File;
+
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
-import java.io.File;
/**
* Created by Olga on 7/15/2016.
diff --git a/spring-mvc-email/src/main/resources/application.properties b/spring-mvc-simple/src/main/resources/application.properties
similarity index 83%
rename from spring-mvc-email/src/main/resources/application.properties
rename to spring-mvc-simple/src/main/resources/application.properties
index 61a42050e5..9a804c07d8 100644
--- a/spring-mvc-email/src/main/resources/application.properties
+++ b/spring-mvc-simple/src/main/resources/application.properties
@@ -1,3 +1,5 @@
+#this property file will have to be loaded explicitly as this is not a Spring Boot project
+
# Gmail SMTP
spring.mail.host=smtp.gmail.com
spring.mail.port=587
diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/views/home.jsp b/spring-mvc-simple/src/main/webapp/WEB-INF/views/emails.jsp
similarity index 100%
rename from spring-mvc-email/src/main/webapp/WEB-INF/views/home.jsp
rename to spring-mvc-simple/src/main/webapp/WEB-INF/views/emails.jsp
diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/views/mail/send.jsp b/spring-mvc-simple/src/main/webapp/WEB-INF/views/mail/send.jsp
similarity index 100%
rename from spring-mvc-email/src/main/webapp/WEB-INF/views/mail/send.jsp
rename to spring-mvc-simple/src/main/webapp/WEB-INF/views/mail/send.jsp
diff --git a/spring-mvc-webflow/pom.xml b/spring-mvc-webflow/pom.xml
index f0a991912a..ec6ccc8ede 100644
--- a/spring-mvc-webflow/pom.xml
+++ b/spring-mvc-webflow/pom.xml
@@ -83,10 +83,10 @@
- 4.3.4.RELEASE
+ 5.0.1.RELEASE
- 2.4.4.RELEASE
+ 2.5.0.RELEASE
3.1.0
1.2
@@ -94,8 +94,6 @@
4.4.5
4.5.2
- 2.9.0
-
2.6
2.7
diff --git a/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java b/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java
index 434f49615b..46bf322f1d 100644
--- a/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java
+++ b/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java
@@ -2,12 +2,10 @@ package org.baeldung.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportResource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
@@ -15,7 +13,7 @@ import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;
@EnableWebMvc
@Configuration
-public class WebMvcConfig extends WebMvcConfigurerAdapter {
+public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private WebFlowConfig webFlowConfig;
diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml b/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml
index ab9eb1a9b7..bad5c5f78c 100644
--- a/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml
+++ b/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml
@@ -2,7 +2,7 @@
+ http://www.springframework.org/schema/webflow/spring-webflow.xsd">
diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md
index 6333b20e11..442a533d1b 100644
--- a/spring-mvc-xml/README.md
+++ b/spring-mvc-xml/README.md
@@ -10,7 +10,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Spring MVC Tutorial](http://www.baeldung.com/spring-mvc-tutorial)
- [Servlet Session Timeout](http://www.baeldung.com/servlet-session-timeout)
-- [Basic Forms with Spring MVC](http://www.baeldung.com/spring-mvc-form-tutorial)
- [Returning Image/Media Data with Spring MVC](http://www.baeldung.com/spring-mvc-image-media-data)
- [Geolocation by IP in Java](http://www.baeldung.com/geolocation-by-ip-with-maxmind)
- [Guide to JavaServer Pages (JSP)](http://www.baeldung.com/jsp)
diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml
index 8ec2ff10e5..6979894f6f 100644
--- a/spring-mvc-xml/pom.xml
+++ b/spring-mvc-xml/pom.xml
@@ -37,13 +37,6 @@
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.9.2
-
-
-
javax.servlet
javax.servlet-api
@@ -127,10 +120,8 @@
5.0.2.RELEASE
- 4.2.0.RELEASE
- 5.2.5.Final
5.1.40
@@ -138,10 +129,10 @@
4.5.2
- 5.3.3.Final
+ 6.0.10.Final
1.2
3.1.0
- 2.8.5
+ 2.9.6
19.0
@@ -149,9 +140,6 @@
2.5
2.8.0
-
- 2.9.0
-
2.6
1.6.1
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java
index b5238b04d5..9752526963 100644
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java
+++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java
@@ -2,11 +2,11 @@ package com.baeldung.spring;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ImportResource("classpath:webMvcConfig.xml")
@Configuration
-public class ClientWebConfig extends WebMvcConfigurerAdapter {
+public class ClientWebConfig implements WebMvcConfigurer {
public ClientWebConfig() {
super();
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
index f299c46dbc..7925fa451d 100644
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
+++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
@@ -9,13 +9,13 @@ import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
//@EnableWebMvc
//@Configuration
-public class ClientWebConfigJava extends WebMvcConfigurerAdapter {
+public class ClientWebConfigJava implements WebMvcConfigurer {
public ClientWebConfigJava() {
super();
@@ -38,8 +38,6 @@ public class ClientWebConfigJava extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
-
registry.addViewController("/sample.html");
}
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java
deleted file mode 100644
index fa76933f8f..0000000000
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.baeldung.spring.controller;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.baeldung.spring.form.Employee;
-
-@Controller
-public class EmployeeController {
-
- Map employeeMap = new HashMap<>();
-
- @RequestMapping(value = "/employee", method = RequestMethod.GET)
- public ModelAndView showForm() {
- return new ModelAndView("employeeHome", "employee", new Employee());
- }
-
- @RequestMapping(value = "/employee/{Id}", produces = { "application/json", "application/xml" }, method = RequestMethod.GET)
- public @ResponseBody Employee getEmployeeById(@PathVariable final long Id) {
- return employeeMap.get(Id);
- }
-
- @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
- public String submit(@ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) {
- if (result.hasErrors()) {
- return "error";
- }
- model.addAttribute("name", employee.getName());
- model.addAttribute("contactNumber", employee.getContactNumber());
- model.addAttribute("id", employee.getId());
- employeeMap.put(employee.getId(), employee);
- return "employeeView";
- }
-
-}
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java
index eeaddcf8e0..0e2fe48160 100644
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java
+++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java
@@ -11,7 +11,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.baeldung.spring.form.GeoIP;
import com.baeldung.spring.service.RawDBDemoGeoIPLocationService;
-@Controller
+//@Controller
+//add db file and uncomment to see the working example
public class GeoIPTestController {
private RawDBDemoGeoIPLocationService locationService;
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java
deleted file mode 100644
index 66b2e9f185..0000000000
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.baeldung.spring.form;
-
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-import javax.xml.bind.annotation.XmlRootElement;
-
-@XmlRootElement
-public class Employee {
-
- private long id;
-
- @NotNull
- @Size(min = 1)
- private String name;
- @NotNull
- @Size(min = 1)
- private String contactNumber;
-
- public Employee() {
- super();
- }
-
- //
-
- public String getName() {
- return name;
- }
-
- public void setName(final String name) {
- this.name = name;
- }
-
- public long getId() {
- return id;
- }
-
- public void setId(final long id) {
- this.id = id;
- }
-
- public String getContactNumber() {
- return contactNumber;
- }
-
- public void setContactNumber(final String contactNumber) {
- this.contactNumber = contactNumber;
- }
-
-}
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java
index 01638fbe76..307a36b10f 100644
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java
+++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java
@@ -2,7 +2,8 @@ package com.baeldung.spring.form;
import java.util.List;
-import org.hibernate.validator.constraints.NotEmpty;
+import javax.validation.constraints.NotEmpty;
+
import org.springframework.web.multipart.MultipartFile;
public class Person {
diff --git a/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml b/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml
index 75d5c1ecd6..8a0671ca87 100644
--- a/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml
+++ b/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml
@@ -4,11 +4,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.3.xsd
+ http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
+ http://www.springframework.org/schema/mvc/spring-mvc.xsd">
diff --git a/spring-mvc-xml/src/main/resources/webMvcConfig.xml b/spring-mvc-xml/src/main/resources/webMvcConfig.xml
index 37aebe1d1d..4bdb405237 100644
--- a/spring-mvc-xml/src/main/resources/webMvcConfig.xml
+++ b/spring-mvc-xml/src/main/resources/webMvcConfig.xml
@@ -3,11 +3,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.3.xsd
+ http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"
+ http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeHome.jsp
deleted file mode 100644
index 588678cdcf..0000000000
--- a/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeHome.jsp
+++ /dev/null
@@ -1,33 +0,0 @@
-<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
-<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
-
-
-
-Form Example - Register an Employee
-
-
- Welcome, Enter The Employee Details
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeView.jsp
deleted file mode 100644
index 1457bc5fc8..0000000000
--- a/spring-mvc-xml/src/main/webapp/WEB-INF/view/employeeView.jsp
+++ /dev/null
@@ -1,24 +0,0 @@
-<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
-
-
-Spring MVC Form Handling
-
-
-
- Submitted Employee Information
-
-
- Name : |
- ${name} |
-
-
- ID : |
- ${id} |
-
-
- Contact Number : |
- ${contactNumber} |
-
-
-
-
\ No newline at end of file
diff --git a/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java
index 0e957f3400..0aa23842b1 100644
--- a/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java
+++ b/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java
@@ -14,10 +14,12 @@ public class GeoIpIntegrationTest {
@Test
public void givenIP_whenFetchingCity_thenReturnsCityData() throws IOException, GeoIp2Exception {
- File database = new File("your-path-to-db-file");
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ File database = new File(classLoader.getResource("GeoLite2-City.mmdb").getFile());
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();
- InetAddress ipAddress = InetAddress.getByName("your-public-ip");
+ InetAddress ipAddress = InetAddress.getByName("google.com");
CityResponse response = dbReader.city(ipAddress);
String countryName = response.getCountry().getName();
diff --git a/spring-mvc-xml/src/test/resources/.gitignore b/spring-mvc-xml/src/test/resources/.gitignore
deleted file mode 100644
index 83c05e60c8..0000000000
--- a/spring-mvc-xml/src/test/resources/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-*.class
-
-#folders#
-/target
-/neoDb*
-/data
-/src/main/webapp/WEB-INF/classes
-*/META-INF/*
-
-# Packaged files #
-*.jar
-*.war
-*.ear
\ No newline at end of file
diff --git a/spring-mvc-xml/src/test/resources/GeoLite2-City.mmdb b/spring-mvc-xml/src/test/resources/GeoLite2-City.mmdb
new file mode 100644
index 0000000000..6de839a7ed
Binary files /dev/null and b/spring-mvc-xml/src/test/resources/GeoLite2-City.mmdb differ
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java b/spring-rest/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java
new file mode 100644
index 0000000000..ebc18a130b
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java
@@ -0,0 +1,14 @@
+package com.baeldung.responseheaders;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+
+@ServletComponentScan
+@SpringBootApplication
+public class ResponseHeadersApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ResponseHeadersApplication.class, args);
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java b/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java
new file mode 100644
index 0000000000..c92d4afafd
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java
@@ -0,0 +1,24 @@
+package com.baeldung.responseheaders.controllers;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/filter-response-header")
+public class FilterResponseHeaderController {
+
+ @GetMapping("/no-extra-header")
+ public String FilterHeaderResponseWithNoExtraHeader() {
+ return "Response body with Filter header and no extra header";
+ }
+
+ @GetMapping("/extra-header")
+ public String FilterHeaderResponseWithExtraHeader(HttpServletResponse response) {
+ response.addHeader("Baeldung-Example-Header", "Value-ExtraHeader");
+ return "Response body with Filter header and one extra header";
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java b/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java
new file mode 100644
index 0000000000..d93964b815
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java
@@ -0,0 +1,70 @@
+package com.baeldung.responseheaders.controllers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/single-response-header")
+public class ResponseHeaderController {
+
+ @GetMapping("/http-servlet-response")
+ public String usingHttpServletResponse(HttpServletResponse response) {
+ response.addHeader("Baeldung-Example-Header", "Value-HttpServletResponse");
+ return "Response with header using HttpServletResponse";
+ }
+
+ @GetMapping("/response-entity-constructor")
+ public ResponseEntity usingResponseEntityConstructor() {
+ HttpHeaders responseHeaders = new HttpHeaders();
+ responseHeaders.set("Baeldung-Example-Header", "Value-ResponseEntityContructor");
+ String responseBody = "Response with header using ResponseEntity (constructor)";
+ HttpStatus responseStatus = HttpStatus.OK;
+
+ return new ResponseEntity(responseBody, responseHeaders, responseStatus);
+ }
+
+ @GetMapping("/response-entity-contructor-multiple-headers")
+ public ResponseEntity usingResponseEntityConstructorAndMultipleHeaders() {
+ List acceptableMediaTypes = new ArrayList<>(Arrays.asList(MediaType.APPLICATION_JSON));
+ HttpHeaders responseHeaders = new HttpHeaders();
+ responseHeaders.set("Baeldung-Example-Header", "Value-ResponseEntityConstructorAndHeaders");
+ responseHeaders.setAccept(acceptableMediaTypes);
+ String responseBody = "Response with header using ResponseEntity (constructor)";
+ HttpStatus responseStatus = HttpStatus.OK;
+
+ return new ResponseEntity(responseBody, responseHeaders, responseStatus);
+ }
+
+ @GetMapping("/response-entity-builder")
+ public ResponseEntity usingResponseEntityBuilder() {
+ String responseHeaderKey = "Baeldung-Example-Header";
+ String responseHeaderValue = "Value-ResponseEntityBuilder";
+ String responseBody = "Response with header using ResponseEntity (builder)";
+
+ return ResponseEntity.ok()
+ .header(responseHeaderKey, responseHeaderValue)
+ .body(responseBody);
+ }
+
+ @GetMapping("/response-entity-builder-with-http-headers")
+ public ResponseEntity usingResponseEntityBuilderAndHttpHeaders() {
+ HttpHeaders responseHeaders = new HttpHeaders();
+ responseHeaders.set("Baeldung-Example-Header", "Value-ResponseEntityBuilderWithHttpHeaders");
+ String responseBody = "Response with header using ResponseEntity (builder)";
+
+ return ResponseEntity.ok()
+ .headers(responseHeaders)
+ .body(responseBody);
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java b/spring-rest/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java
new file mode 100644
index 0000000000..7d4ffb1391
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java
@@ -0,0 +1,41 @@
+package com.baeldung.responseheaders.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@WebFilter("/filter-response-header/*")
+public class AddResponseHeaderFilter implements Filter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AddResponseHeaderFilter.class);
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // add special initialization requirements here
+ LOGGER.trace("Initializing filter...");
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ httpServletResponse.setHeader("Baeldung-Example-Filter-Header", "Value-Filter");
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ // clean up any resource being held by the filter here
+ LOGGER.trace("Destroying filter...");
+ }
+
+}
diff --git a/spring-rest/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java b/spring-rest/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java
new file mode 100644
index 0000000000..bed0de55bd
--- /dev/null
+++ b/spring-rest/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java
@@ -0,0 +1,103 @@
+package com.baeldung.responseheaders;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+public class ResponseHeaderLiveTest {
+
+ private static final String BASE_URL = "http://localhost:8082/spring-rest";
+ private static final String SINGLE_BASE_URL = BASE_URL + "/single-response-header";
+ private static final String FILTER_BASE_URL = BASE_URL + "/filter-response-header";
+ private static final String SERVICE_SINGLE_RESPONSE_HEADER = "Baeldung-Example-Header";
+ private static final String SERVICE_FILTER_RESPONSE_HEADER = "Baeldung-Example-Filter-Header";
+
+ @Autowired
+ private TestRestTemplate template;
+
+ @Test
+ public void whenHttpServletResponseRequest_thenObtainResponseWithCorrectHeader() {
+ final String requestUrl = "/http-servlet-response";
+ ResponseEntity response = template.getForEntity(SINGLE_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-HttpServletResponse"));
+ }
+
+ @Test
+ public void whenResponseEntityConstructorRequest_thenObtainResponseWithCorrectHeader() {
+ final String requestUrl = "/response-entity-constructor";
+ ResponseEntity response = template.getForEntity(SINGLE_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-ResponseEntityContructor"));
+ }
+
+ @Test
+ public void whenResponseEntityConstructorAndMultipleHeadersRequest_thenObtainResponseWithCorrectHeaders() {
+ final String requestUrl = "/response-entity-contructor-multiple-headers";
+ ResponseEntity response = template.getForEntity(SINGLE_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-ResponseEntityConstructorAndHeaders"));
+ assertThat(responseHeaders).containsEntry("Accept", Arrays.asList(MediaType.APPLICATION_JSON.toString()));
+ }
+
+ @Test
+ public void whenResponseEntityBuilderRequest_thenObtainResponseWithCorrectHeader() {
+ final String requestUrl = "/response-entity-builder";
+ ResponseEntity response = template.getForEntity(SINGLE_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-ResponseEntityBuilder"));
+ }
+
+ @Test
+ public void whenResponseEntityBuilderAndHttpHeadersRequest_thenObtainResponseWithCorrectHeader() {
+ final String requestUrl = "/response-entity-builder-with-http-headers";
+ ResponseEntity response = template.getForEntity(SINGLE_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-ResponseEntityBuilderWithHttpHeaders"));
+ }
+
+ @Test
+ public void whenFilterWithNoExtraHeaderRequest_thenObtainResponseWithCorrectHeader() {
+ final String requestUrl = "/no-extra-header";
+ ResponseEntity response = template.getForEntity(FILTER_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_FILTER_RESPONSE_HEADER, Arrays.asList("Value-Filter"));
+ }
+
+ @Test
+ public void whenFilterWithExtraHeaderRequest_thenObtainResponseWithCorrectHeaders() {
+ final String requestUrl = "/extra-header";
+ ResponseEntity response = template.getForEntity(FILTER_BASE_URL + requestUrl, String.class);
+ HttpHeaders responseHeaders = response.getHeaders();
+
+ assertThat(responseHeaders).isNotEmpty();
+ assertThat(responseHeaders).containsEntry(SERVICE_FILTER_RESPONSE_HEADER, Arrays.asList("Value-Filter"));
+ assertThat(responseHeaders).containsEntry(SERVICE_SINGLE_RESPONSE_HEADER, Arrays.asList("Value-ExtraHeader"));
+ }
+
+}
diff --git a/spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateIntegrationTest.java b/spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateLiveTest.java
similarity index 97%
rename from spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateIntegrationTest.java
rename to spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateLiveTest.java
index e0c24c32b1..4f00bebdf4 100644
--- a/spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateIntegrationTest.java
+++ b/spring-rest/src/test/java/org/baeldung/resttemplate/RestTemplateLiveTest.java
@@ -21,7 +21,7 @@ import com.baeldung.transfer.LoginForm;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RestClientConfig.class)
-public class RestTemplateIntegrationTest {
+public class RestTemplateLiveTest {
@Autowired
RestTemplate restTemplate;
diff --git a/spring-security-sso/pom.xml b/spring-security-sso/pom.xml
index f68b9addac..764e899640 100644
--- a/spring-security-sso/pom.xml
+++ b/spring-security-sso/pom.xml
@@ -9,10 +9,10 @@
pom
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -22,7 +22,9 @@
- 3.0.1
-
-
+ 3.1.0
+ 2.3.3.RELEASE
+ 2.0.1.RELEASE
+
+
\ No newline at end of file
diff --git a/spring-security-sso/spring-security-sso-auth-server/pom.xml b/spring-security-sso/spring-security-sso-auth-server/pom.xml
index 0d0086beb0..f506deccf7 100644
--- a/spring-security-sso/spring-security-sso-auth-server/pom.xml
+++ b/spring-security-sso/spring-security-sso-auth-server/pom.xml
@@ -21,6 +21,7 @@
org.springframework.security.oauth
spring-security-oauth2
+ ${oauth.version}
diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java
index 20cde21073..56229d4d38 100644
--- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java
+++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java
@@ -2,19 +2,20 @@ package org.baeldung.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
-import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
- @Autowired
- private AuthenticationManager authenticationManager;
-
+
+ @Autowired
+ private BCryptPasswordEncoder passwordEncoder;
+
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
@@ -25,17 +26,14 @@ public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("SampleClientId")
- .secret("secret")
+ .secret(passwordEncoder.encode("secret"))
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true)
+ .redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login")
// .accessTokenValiditySeconds(3600)
; // 1 hour
}
- @Override
- public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
- endpoints.authenticationManager(authenticationManager);
- }
}
diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthorizationServerApplication.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthorizationServerApplication.java
index 5b0b39b444..b74d2f144c 100644
--- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthorizationServerApplication.java
+++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthorizationServerApplication.java
@@ -2,7 +2,7 @@ package org.baeldung.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
@SpringBootApplication
diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java
index a568c22eec..5cebf4f4d2 100644
--- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java
+++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java
@@ -1,18 +1,17 @@
package org.baeldung.config;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
+@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Autowired
- private AuthenticationManager authenticationManager;
-
+
@Override
protected void configure(HttpSecurity http) throws Exception { // @formatter:off
http.requestMatchers()
@@ -28,11 +27,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off
- auth.parentAuthenticationManager(authenticationManager)
- .inMemoryAuthentication()
+ auth.inMemoryAuthentication()
.withUser("john")
- .password("123")
+ .password(passwordEncoder().encode("123"))
.roles("USER");
} // @formatter:on
+ @Bean
+ public BCryptPasswordEncoder passwordEncoder(){
+ return new BCryptPasswordEncoder();
+ }
}
diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/resources/application.properties b/spring-security-sso/spring-security-sso-auth-server/src/main/resources/application.properties
index 32a0993b04..066123118f 100644
--- a/spring-security-sso/spring-security-sso-auth-server/src/main/resources/application.properties
+++ b/spring-security-sso/spring-security-sso-auth-server/src/main/resources/application.properties
@@ -1,4 +1,3 @@
server.port=8081
-server.context-path=/auth
-security.basic.enabled=false
+server.servlet.context-path=/auth
#logging.level.org.springframework=DEBUG
\ No newline at end of file
diff --git a/spring-security-sso/spring-security-sso-ui-2/pom.xml b/spring-security-sso/spring-security-sso-ui-2/pom.xml
index a2323a044d..c38c855a30 100644
--- a/spring-security-sso/spring-security-sso-ui-2/pom.xml
+++ b/spring-security-sso/spring-security-sso-ui-2/pom.xml
@@ -25,8 +25,9 @@
- org.springframework.security.oauth
- spring-security-oauth2
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ ${oauth-auto.version}
diff --git a/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiApplication.java b/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiApplication.java
index a222224c59..0c20853aed 100644
--- a/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiApplication.java
+++ b/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiApplication.java
@@ -2,7 +2,7 @@ package org.baeldung.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.context.request.RequestContextListener;
diff --git a/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiSecurityConfig.java b/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiSecurityConfig.java
index f9119e20f5..de81ada9e0 100644
--- a/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiSecurityConfig.java
+++ b/spring-security-sso/spring-security-sso-ui-2/src/main/java/org/baeldung/config/UiSecurityConfig.java
@@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
@EnableOAuth2Sso
@Configuration
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
diff --git a/spring-security-sso/spring-security-sso-ui-2/src/main/resources/application.yml b/spring-security-sso/spring-security-sso-ui-2/src/main/resources/application.yml
index 6b0d3db5ad..97c8de7839 100644
--- a/spring-security-sso/spring-security-sso-ui-2/src/main/resources/application.yml
+++ b/spring-security-sso/spring-security-sso-ui-2/src/main/resources/application.yml
@@ -1,6 +1,7 @@
server:
port: 8083
- context-path: /ui2
+ servlet:
+ context-path: /ui2
session:
cookie:
name: UI2SESSION
diff --git a/spring-security-sso/spring-security-sso-ui/pom.xml b/spring-security-sso/spring-security-sso-ui/pom.xml
index dbb167b61c..6a0b630502 100644
--- a/spring-security-sso/spring-security-sso-ui/pom.xml
+++ b/spring-security-sso/spring-security-sso-ui/pom.xml
@@ -23,11 +23,13 @@
org.springframework.boot
spring-boot-starter-security
-
+
- org.springframework.security.oauth
- spring-security-oauth2
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ ${oauth-auto.version}
+
org.springframework.boot
diff --git a/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiApplication.java b/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiApplication.java
index e186046e83..07d875d805 100644
--- a/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiApplication.java
+++ b/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiApplication.java
@@ -2,7 +2,7 @@ package org.baeldung.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.context.request.RequestContextListener;
diff --git a/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiSecurityConfig.java b/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiSecurityConfig.java
index f9119e20f5..de81ada9e0 100644
--- a/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiSecurityConfig.java
+++ b/spring-security-sso/spring-security-sso-ui/src/main/java/org/baeldung/config/UiSecurityConfig.java
@@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
@EnableOAuth2Sso
@Configuration
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
diff --git a/spring-security-sso/spring-security-sso-ui/src/main/resources/application.yml b/spring-security-sso/spring-security-sso-ui/src/main/resources/application.yml
index bb4bd92033..d1d9ea6ebc 100644
--- a/spring-security-sso/spring-security-sso-ui/src/main/resources/application.yml
+++ b/spring-security-sso/spring-security-sso-ui/src/main/resources/application.yml
@@ -1,6 +1,7 @@
server:
port: 8082
- context-path: /ui
+ servlet:
+ context-path: /ui
session:
cookie:
name: UISESSION
diff --git a/spring-session/pom.xml b/spring-session/pom.xml
index 4c256663b0..277b033f43 100644
--- a/spring-session/pom.xml
+++ b/spring-session/pom.xml
@@ -30,6 +30,15 @@
org.springframework.boot
spring-boot-starter-web
+
+ com.github.kstyrc
+ embedded-redis
+ ${embedded-redis.version}
+
+
+
+ 0.6
+
\ No newline at end of file
diff --git a/spring-session/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java b/spring-session/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
index 84dd2bc139..f739aeb3ab 100644
--- a/spring-session/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
+++ b/spring-session/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
@@ -1,27 +1,55 @@
package com.baeldung.spring.session;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.boot.test.web.client.TestRestTemplate;
-import org.springframework.http.*;
-import redis.clients.jedis.Jedis;
-
-import java.util.Set;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import redis.clients.jedis.Jedis;
+import redis.embedded.RedisServer;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = SessionWebApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
public class SessionControllerIntegrationTest {
private Jedis jedis;
+ private static RedisServer redisServer;
private TestRestTemplate testRestTemplate;
private TestRestTemplate testRestTemplateWithAuth;
private String testUrl = "http://localhost:8080/";
+ @BeforeClass
+ public static void startRedisServer() throws IOException {
+ redisServer = new RedisServer(6379);
+ redisServer.start();
+ }
+
+ @AfterClass
+ public static void stopRedisServer() throws IOException {
+ redisServer.stop();
+ }
+
@Before
public void clearRedisData() {
+
testRestTemplate = new TestRestTemplate();
- testRestTemplateWithAuth = new TestRestTemplate("admin", "password", null);
+ testRestTemplateWithAuth = new TestRestTemplate("admin", "password");
jedis = new Jedis("localhost", 6379);
jedis.flushAll();
diff --git a/spring-userservice/pom.xml b/spring-userservice/pom.xml
index c372beaa3c..a6acfe3fc6 100644
--- a/spring-userservice/pom.xml
+++ b/spring-userservice/pom.xml
@@ -217,11 +217,11 @@
4.2.6.RELEASE
- 1.4.2.RELEASE
+ 1.5.14.RELEASE
3.21.0-GA
- 5.2.5.Final
+ 5.2.10.Final
5.1.40
1.10.5.RELEASE
1.4.193
diff --git a/spring-userservice/src/main/resources/persistence-derby.properties b/spring-userservice/src/main/resources/persistence-derby.properties
index e808fdc288..b76c5de12f 100644
--- a/spring-userservice/src/main/resources/persistence-derby.properties
+++ b/spring-userservice/src/main/resources/persistence-derby.properties
@@ -7,6 +7,6 @@ jdbc.pass=tutorialpass
# hibernate.X
hibernate.dialect=org.hibernate.dialect.DerbyDialect
hibernate.show_sql=false
-hibernate.hbm2ddl.auto=create
+hibernate.hbm2ddl.auto=update
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false
\ No newline at end of file
diff --git a/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceIntegrationTest.java b/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceIntegrationTest.java
index f46a3a070f..1cd38228b8 100644
--- a/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceIntegrationTest.java
+++ b/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceIntegrationTest.java
@@ -1,5 +1,10 @@
package org.baeldung.userservice;
+import static org.junit.Assert.assertEquals;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
import org.baeldung.custom.config.MvcConfig;
import org.baeldung.custom.config.PersistenceDerbyJPAConfig;
import org.baeldung.custom.config.SecSecurityConfig;
@@ -8,22 +13,16 @@ import org.baeldung.web.MyUserDto;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.dao.DuplicateKeyException;
+import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
-import static org.junit.Assert.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = { MvcConfig.class, PersistenceDerbyJPAConfig.class, SecSecurityConfig.class })
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = { MvcConfig.class, PersistenceDerbyJPAConfig.class, SecSecurityConfig.class })
@WebAppConfiguration
public class CustomUserDetailsServiceIntegrationTest {