diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md
index 82d9df9292..87a1ee15ec 100644
--- a/algorithms-modules/algorithms-miscellaneous-7/README.md
+++ b/algorithms-modules/algorithms-miscellaneous-7/README.md
@@ -4,4 +4,5 @@
- [Find the N Most Frequent Elements in a Java Array](https://www.baeldung.com/java-n-most-frequent-elements-array)
- [Getting Pixel Array From Image in Java](https://www.baeldung.com/java-getting-pixel-array-from-image)
- [Calculate Distance Between Two Coordinates in Java](https://www.baeldung.com/java-find-distance-between-points)
+- [Rotate Arrays in Java](https://www.baeldung.com/java-rotate-arrays)
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
diff --git a/apache-poi-3/pom.xml b/apache-poi-3/pom.xml
index 905db3d58c..e6e85d1212 100644
--- a/apache-poi-3/pom.xml
+++ b/apache-poi-3/pom.xml
@@ -1,7 +1,7 @@
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
apache-poi-3
0.0.1-SNAPSHOT
diff --git a/aws-modules/aws-s3-update-object/pom.xml b/aws-modules/aws-s3-update-object/pom.xml
deleted file mode 100644
index 3cf7b657b0..0000000000
--- a/aws-modules/aws-s3-update-object/pom.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
- 4.0.0
- aws-s3-update-object
- 0.0.1-SNAPSHOT
- aws-s3-update-object
- Project demonstrating overwriting of S3 objects
-
- com.baeldung
- parent-boot-2
- 0.0.1-SNAPSHOT
- ../../parent-boot-2
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- com.amazonaws
- aws-java-sdk
- ${aws-java-sdk-version}
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
- 1.12.523
-
-
diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java
deleted file mode 100644
index 24866c287b..0000000000
--- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.baeldung.awss3updateobject;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class AwsS3UpdateObjectApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(AwsS3UpdateObjectApplication.class, args);
- }
-
-}
diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java
deleted file mode 100644
index e87358ef56..0000000000
--- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.baeldung.awss3updateobject.controller;
-
-import com.baeldung.awss3updateobject.service.FileService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-@RestController
-@RequestMapping("api/v1/file")
-public class FileController {
-
- @Autowired
- FileService fileService;
-
- @PostMapping("/upload")
- public String uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception {
- return this.fileService.uploadFile(multipartFile);
- }
-
- @PostMapping("/update")
- public String updateFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam("filePath") String exitingFilePath) throws Exception {
- return this.fileService.updateFile(multipartFile, exitingFilePath);
- }
-}
diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java
deleted file mode 100644
index 23eaad7913..0000000000
--- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.baeldung.awss3updateobject.service;
-
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.regions.Regions;
-import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.AmazonS3ClientBuilder;
-import com.amazonaws.services.s3.model.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.annotation.PostConstruct;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-@Service
-public class FileService {
-
- private static final Logger logger = LoggerFactory.getLogger(FileService.class);
-
- public AmazonS3 amazonS3;
-
- @Value("${aws.s3bucket}")
- public String awsS3Bucket;
-
- @PostConstruct
- private void init(){
- AWSCredentials credentials = new BasicAWSCredentials(
- "AWS AccessKey",
- "AWS secretKey"
- );
- this.amazonS3 = AmazonS3ClientBuilder.standard()
- .withRegion(Regions.fromName("us-east-1"))
- .withCredentials(new AWSStaticCredentialsProvider(credentials))
- .build();
- }
-
- public String uploadFile(MultipartFile multipartFile) throws Exception {
- String key = "/documents/" + multipartFile.getOriginalFilename();
- return this.uploadDocument(this.awsS3Bucket, key, multipartFile);
- }
-
- public String updateFile(MultipartFile multipartFile, String key) throws Exception {
- return this.uploadDocument(this.awsS3Bucket, key, multipartFile);
- }
-
- private String uploadDocument(String s3bucket, String key, MultipartFile multipartFile) throws Exception {
- try {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentType(multipartFile.getContentType());
- Map attributes = new HashMap<>();
- attributes.put("document-content-size", String.valueOf(multipartFile.getSize()));
- metadata.setUserMetadata(attributes);
- InputStream documentStream = multipartFile.getInputStream();
- PutObjectResult putObjectResult = this.amazonS3.putObject(new PutObjectRequest(s3bucket, key, documentStream, metadata));
-
- S3Object s3Object = this.amazonS3.getObject(s3bucket, key);
- logger.info("Last Modified: " + s3Object.getObjectMetadata().getLastModified());
- return key;
- } catch (AmazonS3Exception ex) {
- if (ex.getErrorCode().equalsIgnoreCase("NoSuchBucket")) {
- String msg = String.format("No bucket found with name %s", s3bucket);
- throw new Exception(msg);
- } else if (ex.getErrorCode().equalsIgnoreCase("AccessDenied")) {
- String msg = String.format("Access denied to S3 bucket %s", s3bucket);
- throw new Exception(msg);
- }
- throw ex;
- } catch (IOException ex) {
- String msg = String.format("Error saving file %s to AWS S3 bucket %s", key, s3bucket);
- throw new Exception(msg);
- }
- }
-}
diff --git a/aws-modules/aws-s3-update-object/src/main/resources/application.properties b/aws-modules/aws-s3-update-object/src/main/resources/application.properties
deleted file mode 100644
index c840d970a8..0000000000
--- a/aws-modules/aws-s3-update-object/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-aws.s3bucket=baeldung-documents;
diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java
deleted file mode 100644
index 823391c139..0000000000
--- a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.baeldung.awss3updateobject.controller;
-
-import com.baeldung.awss3updateobject.service.FileService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.mock.web.MockMultipartFile;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import org.springframework.web.multipart.MultipartFile;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.*;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-
-public class FileControllerUnitTest {
-
- private MockMvc mockMvc;
-
- @Mock
- private FileService fileService;
-
- @InjectMocks
- private FileController fileController;
-
- @BeforeEach
- public void setUp() {
- MockitoAnnotations.openMocks(this);
- this.mockMvc = MockMvcBuilders.standaloneSetup(fileController).build();
- }
-
- @Test
- public void givenValidMultipartFile_whenUploadedViaEndpoint_thenCorrectPathIsReturned() throws Exception {
- MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "sample file content".getBytes());
- String expectedResult = "File Uploaded Successfully";
-
- when(fileService.uploadFile(multipartFile)).thenReturn(expectedResult);
-
- mockMvc.perform(multipart("/api/v1/file/upload").file(multipartFile))
- .andExpect(status().isOk())
- .andExpect(content().string(expectedResult));
- }
-
- @Test
- public void givenValidMultipartFileAndExistingPath_whenUpdatedViaEndpoint_thenSamePathIsReturned() throws Exception {
- MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "updated file content".getBytes());
- String filePath = "some/path/to/file";
- String expectedResult = "File Updated Successfully";
-
- when(fileService.updateFile(multipartFile, filePath)).thenReturn(expectedResult);
-
- mockMvc.perform(multipart("/api/v1/file/update")
- .file(multipartFile)
- .param("filePath", filePath))
- .andExpect(status().isOk())
- .andExpect(content().string(expectedResult));
- }
-}
\ No newline at end of file
diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java
deleted file mode 100644
index 90ed77b148..0000000000
--- a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.baeldung.awss3updateobject.service;
-
-import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.model.AmazonS3Exception;
-import com.amazonaws.services.s3.model.PutObjectRequest;
-import com.amazonaws.services.s3.model.S3Object;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-
-public class FileServiceUnitTest {
-
- @Mock
- private AmazonS3 amazonS3;
-
- @Mock
- private MultipartFile multipartFile;
-
- @InjectMocks
- private FileService fileService;
-
- @BeforeEach
- public void setup() {
- MockitoAnnotations.openMocks(this);
- fileService = new FileService();
- fileService.awsS3Bucket = "test-bucket";
- fileService.amazonS3 = amazonS3;
- }
-
- @Test
- public void givenValidFile_whenUploaded_thenKeyMatchesDocumentPath() throws Exception {
- when(multipartFile.getName()).thenReturn("testFile");
- when(multipartFile.getOriginalFilename()).thenReturn("testFile");
- when(multipartFile.getContentType()).thenReturn("application/pdf");
- when(multipartFile.getSize()).thenReturn(1024L);
- when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
-
- S3Object s3Object = new S3Object();
- when(amazonS3.putObject(any())).thenReturn(null);
- when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object);
-
- String key = fileService.uploadFile(multipartFile);
-
- assertEquals("/documents/testFile", key);
- }
-
- @Test
- public void givenValidFile_whenUploadFailsDueToNoBucket_thenExceptionIsThrown() throws Exception {
- when(multipartFile.getName()).thenReturn("testFile");
- when(multipartFile.getOriginalFilename()).thenReturn("testFile");
- when(multipartFile.getContentType()).thenReturn("application/pdf");
- when(multipartFile.getSize()).thenReturn(1024L);
- when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
-
- AmazonS3Exception exception = new AmazonS3Exception("Test exception");
- exception.setErrorCode("NoSuchBucket");
- when(amazonS3.putObject(any(PutObjectRequest.class))).thenThrow(exception);
-
- assertThrows(Exception.class, () -> fileService.uploadFile(multipartFile));
- }
-
- @Test
- public void givenExistingFile_whenUpdated_thenSameKeyIsReturned() throws Exception {
- when(multipartFile.getName()).thenReturn("testFile");
- when(multipartFile.getContentType()).thenReturn("application/pdf");
- when(multipartFile.getSize()).thenReturn(1024L);
- when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
-
- S3Object s3Object = new S3Object();
- when(amazonS3.putObject(any(PutObjectRequest.class))).thenReturn(null);
- when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object);
-
- String key = "/documents/existingFile";
- String resultKey = fileService.updateFile(multipartFile, key);
-
- assertEquals(key, resultKey);
- }
-
- @Test
- public void givenFileWithIOException_whenUpdated_thenExceptionIsThrown() throws Exception {
- when(multipartFile.getName()).thenReturn("testFile");
- when(multipartFile.getContentType()).thenReturn("application/pdf");
- when(multipartFile.getSize()).thenReturn(1024L);
- when(multipartFile.getInputStream()).thenThrow(new IOException("Test IO Exception"));
-
- assertThrows(Exception.class, () -> fileService.updateFile(multipartFile, "/documents/existingFile"));
- }
-}
\ No newline at end of file
diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md
index 9b862c8685..f3b34b584e 100644
--- a/aws-modules/aws-s3/README.md
+++ b/aws-modules/aws-s3/README.md
@@ -11,3 +11,4 @@ This module contains articles about Simple Storage Service (S3) on AWS
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)
- [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders)
+- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)
diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java
index abf570f0d0..3328006bc0 100644
--- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java
+++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java
@@ -45,6 +45,13 @@ public class S3Application {
new File("/Users/user/Document/hello.txt")
);
+ s3Service.updateObject(
+ AWS_BUCKET,
+ "Document/hello2.txt",
+ new File("/Users/user/Document/hello2.txt")
+ );
+
+
//listing objects
s3Service.listObjects(AWS_BUCKET);
diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java
index f4f768d1b4..dfc8e9de5f 100644
--- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java
+++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java
@@ -24,6 +24,7 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
+import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
@@ -99,7 +100,13 @@ class S3Service {
.key(key)
.build();
- return s3Client.putObject(request, Path.of(file.toURI()) );
+
+ return s3Client.putObject(request, Path.of(file.toURI()));
+ }
+
+ //updating object
+ public PutObjectResponse updateObject(String bucketName, String key, java.io.File file) {
+ return this.putObject(bucketName, key, file);
}
//listing objects
@@ -110,6 +117,7 @@ class S3Service {
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
for(S3Object os : listObjectsV2Response.contents()) {
+
System.out.println(os.key());
}
}
diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java
index bf24bcaa43..15db15831c 100644
--- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java
+++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java
@@ -11,6 +11,8 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.io.File;
+import java.nio.file.Path;
import java.util.Collections;
import software.amazon.awssdk.services.s3.S3Client;
@@ -23,6 +25,7 @@ import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
+import software.amazon.awssdk.services.s3.model.PutObjectRequest;
class S3ServiceIntegrationTest {
@@ -38,6 +41,8 @@ class S3ServiceIntegrationTest {
private final String AWS_BUCKET = "baeldung-tutorial-s3";
+ private File file = new File("/Users/user/Document/hello2.txt");
+
@BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
@@ -75,6 +80,17 @@ class S3ServiceIntegrationTest {
verify(s3Client).createBucket(bucketRequest);
}
+ @Test
+ void whenVerifyingUploadOfS3Object_thenCorrect() {
+ PutObjectRequest request = PutObjectRequest.builder()
+ .bucket(BUCKET_NAME)
+ .key(KEY_NAME)
+ .build();
+
+ s3Service.putObject(BUCKET_NAME, KEY_NAME, file);
+ verify(s3Client).putObject(request, Path.of(file.toURI()) );
+ }
+
@Test
void whenVerifyingListBuckets_thenCorrect() {
when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build());
diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml
index 66fa4bffa1..06cea2f260 100644
--- a/aws-modules/pom.xml
+++ b/aws-modules/pom.xml
@@ -28,7 +28,6 @@
aws-miscellaneous
aws-reactive
aws-s3
- aws-s3-update-object
diff --git a/core-java-modules/core-java-17/README.md b/core-java-modules/core-java-17/README.md
index 2d4a2e0382..4b1125532d 100644
--- a/core-java-modules/core-java-17/README.md
+++ b/core-java-modules/core-java-17/README.md
@@ -8,3 +8,4 @@
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
- [Format Multiple ‘or’ Conditions in an If Statement in Java](https://www.baeldung.com/java-multiple-or-conditions-if-statement)
+- [Get All Record Fields and Its Values via Reflection](https://www.baeldung.com/java-reflection-record-fields-values)
diff --git a/core-java-modules/core-java-18/README.md b/core-java-modules/core-java-18/README.md
index e69de29bb2..63772e96b3 100644
--- a/core-java-modules/core-java-18/README.md
+++ b/core-java-modules/core-java-18/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles
+- [Deprecate Finalization in Java 18](https://www.baeldung.com/java-18-deprecate-finalization)
diff --git a/core-java-modules/core-java-21/pom.xml b/core-java-modules/core-java-21/pom.xml
index 7b8fa9063f..bfe1cd2c78 100644
--- a/core-java-modules/core-java-21/pom.xml
+++ b/core-java-modules/core-java-21/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-21
core-java-21
@@ -12,12 +12,6 @@
0.0.1-SNAPSHOT
-
- 21
- 21
- UTF-8
-
-
@@ -44,4 +38,10 @@
+
+ 21
+ 21
+ UTF-8
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml
index 53cccb8a73..a0ae2398a4 100644
--- a/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml
+++ b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-arrays-operations-advanced-2
core-java-arrays-operations-advanced-2
diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java
new file mode 100644
index 0000000000..66cfade866
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.removequeueelements;
+
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RemoveQueueElementsUnitTest {
+ @Test
+ public void givenQueueWithEvenAndOddNumbers_whenRemovingEvenNumbers_thenOddNumbersRemain() {
+ Queue queue = new LinkedList<>();
+ Queue evenElementsQueue = new LinkedList<>();
+ queue.add(1);
+ queue.add(2);
+ queue.add(3);
+ queue.add(4);
+ queue.add(5);
+
+ while (queue.peek() != null) {
+ int element = queue.remove();
+ if (element % 2 != 0) {
+ evenElementsQueue.add(element);
+ }
+ }
+
+ assertEquals(3, evenElementsQueue.size());
+ assertTrue(evenElementsQueue.contains(1));
+ assertTrue(evenElementsQueue.contains(3));
+ assertTrue(evenElementsQueue.contains(5));
+ }
+
+ @Test
+ public void givenStringQueue_whenRemovingStringsThatStartWithA_thenStringElementsRemain() {
+ Queue queue = new LinkedList<>();
+ Queue stringElementsQueue = new LinkedList<>();
+ queue.add("Apple");
+ queue.add("Banana");
+ queue.add("Orange");
+ queue.add("Grape");
+ queue.add("Mango");
+
+
+ while (queue.peek() != null) {
+ String element = queue.remove();
+ if (!element.startsWith("A")) {
+ stringElementsQueue.add(element);
+ }
+ }
+
+ assertEquals(4, stringElementsQueue.size());
+ assertTrue(stringElementsQueue.contains("Banana"));
+ assertTrue(stringElementsQueue.contains("Orange"));
+ assertTrue(stringElementsQueue.contains("Grape"));
+ assertTrue(stringElementsQueue.contains("Mango"));
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-array-list-2/pom.xml b/core-java-modules/core-java-collections-array-list-2/pom.xml
index 042f6e5bb5..901a4f5c75 100644
--- a/core-java-modules/core-java-collections-array-list-2/pom.xml
+++ b/core-java-modules/core-java-collections-array-list-2/pom.xml
@@ -1,17 +1,17 @@
-
4.0.0
core-java-collections-array-list-2
core-java-collections-array-list-2
jar
+
com.baeldung.core-java-modules
core-java-modules
0.0.1-SNAPSHOT
-
+
@@ -24,7 +24,7 @@
-
+
17
17
diff --git a/core-java-modules/core-java-collections-conversions-3/README.md b/core-java-modules/core-java-collections-conversions-3/README.md
index 653f518840..959e4e8160 100644
--- a/core-java-modules/core-java-collections-conversions-3/README.md
+++ b/core-java-modules/core-java-collections-conversions-3/README.md
@@ -4,3 +4,4 @@ This module contains articles about conversions among Collection types in Java.
### Relevant Articles:
- [Converting HashMap Values to an ArrayList in Java](https://www.baeldung.com/java-hashmap-arraylist)
+- [Joining a List in Java With Commas and “and”](https://www.baeldung.com/java-string-concatenation-natural-language)
diff --git a/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/listoflists/ListOfListsUnitTest.java b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/listoflists/ListOfListsUnitTest.java
index 321fa475f6..f75ca453ea 100644
--- a/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/listoflists/ListOfListsUnitTest.java
+++ b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/listoflists/ListOfListsUnitTest.java
@@ -71,4 +71,15 @@ public class ListOfListsUnitTest {
assertThat(listOfLists.get(2)).containsExactly("Slack", "Zoom", "Microsoft Teams", "Telegram");
printListOfLists(listOfLists);
}
-}
+
+ @Test
+ void givenListOfLists_whenGettingSizeOfSubListsAndSizeOfElements_thenGetExpectedResults() throws URISyntaxException, IOException {
+ List> listOfLists = getListOfListsFromCsv();
+ // size of inner lists
+ assertThat(listOfLists).hasSize(3);
+
+ // size of all elements in subLists
+ int totalElements = listOfLists.stream().mapToInt(List::size).sum();
+ assertThat(totalElements).isEqualTo(12);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-list-6/pom.xml b/core-java-modules/core-java-collections-list-6/pom.xml
index 9bea6358c4..46ef4ff4c9 100644
--- a/core-java-modules/core-java-collections-list-6/pom.xml
+++ b/core-java-modules/core-java-collections-list-6/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-collections-list-6
core-java-collections-list-6
@@ -12,4 +12,5 @@
core-java-modules
0.0.1-SNAPSHOT
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-6/README.md b/core-java-modules/core-java-collections-maps-6/README.md
index d4f432bdcb..f116d0315e 100644
--- a/core-java-modules/core-java-collections-maps-6/README.md
+++ b/core-java-modules/core-java-collections-maps-6/README.md
@@ -9,3 +9,4 @@
- [Converting String or String Array to Map in Java](https://www.baeldung.com/java-convert-string-to-map)
- [Remove Duplicate Values From HashMap in Java](https://www.baeldung.com/java-hashmap-delete-duplicates)
- [Sorting Java Map in Descending Order](https://www.baeldung.com/java-sort-map-descending)
+- [Convert HashMap.toString() to HashMap in Java](https://www.baeldung.com/hashmap-from-tostring)
diff --git a/core-java-modules/core-java-collections-maps-7/README.md b/core-java-modules/core-java-collections-maps-7/README.md
index c63f3b360b..2724df5695 100644
--- a/core-java-modules/core-java-collections-maps-7/README.md
+++ b/core-java-modules/core-java-collections-maps-7/README.md
@@ -1 +1,2 @@
-## Relevant Articles
\ No newline at end of file
+## Relevant Articles
+- [Difference Between putIfAbsent() and computeIfAbsent() in Java’s Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent)
diff --git a/core-java-modules/core-java-collections-maps-7/pom.xml b/core-java-modules/core-java-collections-maps-7/pom.xml
index bb7c6e9fb5..bcc0915073 100644
--- a/core-java-modules/core-java-collections-maps-7/pom.xml
+++ b/core-java-modules/core-java-collections-maps-7/pom.xml
@@ -73,6 +73,11 @@
4.13.1
test
+
+ org.apache.commons
+ commons-csv
+ 1.5
+
-
\ No newline at end of file
+
diff --git a/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java b/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java
index ddebaf2468..e23a5da8ff 100644
--- a/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java
+++ b/core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/writehashmaptocsvfile/WriteHashmaptoCVSFileUnitTest.java
@@ -10,18 +10,26 @@ import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class WriteHashmaptoCVSFileUnitTest {
+ public Map employeeData;
- @Test
- public void givenEmployeeData_whenWriteToCSV_thenCSVFileIsCreated() {
- Map employeeData = new HashMap<>();
+ public WriteHashmaptoCVSFileUnitTest() {
+ employeeData = new HashMap<>();
employeeData.put("Name", "John Doe");
employeeData.put("Title", "Software Engineer");
employeeData.put("Department", "Engineering");
employeeData.put("Salary", "75000");
+ }
+
+ @Test
+ public void givenEmployeeData_whenWriteToCSVUsingFileWriter_thenCSVFileIsCreated() {
+
try (FileWriter csvWriter = new FileWriter("employee_data.csv")) {
// Write header row
csvWriter.append("Name,Title,Department,Salary\n");
@@ -40,23 +48,19 @@ public class WriteHashmaptoCVSFileUnitTest {
}
@Test
- public void givenCSVFile_whenRead_thenContentsMatchExpected() {
- // Read the actual content of the CSV file
- StringBuilder actualCsvContent = new StringBuilder();
- try {
- Files.lines(Paths.get("employee_data.csv"))
- .forEach(line -> actualCsvContent.append(line).append("\n"));
+ public void givenCSVFile_whenWriteToCSVUsingApacheCommons_thenContentsMatchExpected() {
- // Define the expected CSV content
- String expectedCsvContent = "Name,Title,Department,Salary\n" +
- "John Doe,Software Engineer,Engineering,75000\n";
+ try (CSVPrinter csvPrinter = new CSVPrinter(new FileWriter("employee_data2.csv"), CSVFormat.DEFAULT)) {
+ // Write header row
+ csvPrinter.printRecord("Name", "Title", "Department", "Salary");
- // Compare the actual content with the expected content
- assertEquals(expectedCsvContent, actualCsvContent.toString());
-
- System.out.println("CSV file created successfully.");
+ // Write data row
+ csvPrinter.printRecord(employeeData.get("Name"), employeeData.get("Title"), employeeData.get("Department"), employeeData.get("Salary"));
} catch (IOException e) {
e.printStackTrace();
}
+
+ // Ensure the CSV file exists
+ assertTrue(new File("employee_data2.csv").exists());
}
}
diff --git a/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/Main.java b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/Main.java
index dfe8fcbd5a..b693bb1219 100644
--- a/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/Main.java
+++ b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/Main.java
@@ -20,8 +20,9 @@ public class Main {
System.out.println("General exception");
}
- checkedException();
+ checkedExceptionWithTryCatch();
checkedExceptionWithThrows();
+ divideByZero();
}
private static void checkedExceptionWithThrows() throws FileNotFoundException {
@@ -29,7 +30,7 @@ public class Main {
FileInputStream stream = new FileInputStream(file);
}
- private static void checkedException() {
+ private static void checkedExceptionWithTryCatch() {
File file = new File("not_existing_file.txt");
try {
FileInputStream stream = new FileInputStream(file);
@@ -37,5 +38,11 @@ public class Main {
e.printStackTrace();
}
}
+
+ private static void divideByZero() {
+ int numerator = 1;
+ int denominator = 0;
+ int result = numerator / denominator;
+ }
}
diff --git a/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/NullOrEmptyException.java b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/NullOrEmptyException.java
new file mode 100644
index 0000000000..419fb438f2
--- /dev/null
+++ b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/throwvsthrows/NullOrEmptyException.java
@@ -0,0 +1,8 @@
+package com.baeldung.exceptions.throwvsthrows;
+
+public class NullOrEmptyException extends RuntimeException {
+
+ public NullOrEmptyException(String errorMessage) {
+ super(errorMessage);
+ }
+}
diff --git a/core-java-modules/core-java-io-5/README.md b/core-java-modules/core-java-io-5/README.md
index 9fb4b967a4..3cc514e087 100644
--- a/core-java-modules/core-java-io-5/README.md
+++ b/core-java-modules/core-java-io-5/README.md
@@ -4,5 +4,6 @@ This module contains articles about core Java input and output (IO)
### Relevant Articles:
- [Get File Extension From MIME Type in Java](https://www.baeldung.com/java-mime-type-file-extension)
+- [How to Remove Line Breaks From a File in Java](https://www.baeldung.com/java-file-remove-line-breaks)
- [[<-- Prev]](/core-java-modules/core-java-io-4)
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/sizebenchmark/FileSizeBenchmark.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/sizebenchmark/FileSizeBenchmark.java
new file mode 100644
index 0000000000..5998b0be73
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/baeldung/sizebenchmark/FileSizeBenchmark.java
@@ -0,0 +1,67 @@
+package com.baeldung.sizebenchmark;
+
+import org.apache.commons.io.FileUtils;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@Warmup(iterations = 3, time = 10, timeUnit = TimeUnit.NANOSECONDS)
+@Measurement(iterations = 3, time = 10, timeUnit = TimeUnit.NANOSECONDS)
+public class FileSizeBenchmark {
+
+ public static void main(String[] args) throws Exception {
+ org.openjdk.jmh.Main.main(args);
+ }
+
+ @Benchmark
+ public void getFileSizeUsingLengthMethod(Blackhole blackhole) throws Exception {
+ File file = new File("src/test/resources/size/sample_file_1.in");
+ blackhole.consume(file.length());
+ }
+
+ @Benchmark
+ public void getFileSizeUsingFileInputStream(Blackhole blackhole) throws Exception {
+ try (FileInputStream fis = new FileInputStream("src/test/resources/size/sample_file_1.in")) {
+ long result = fis.getChannel().size();
+ blackhole.consume(result);
+ }
+
+ }
+
+ @Benchmark
+ public void getFileSizeUsingInputStreamAndUrl(Blackhole blackhole) throws Exception {
+ File me = new File("src/test/resources/size/sample_file_1.in");
+ URL url = me.toURI().toURL();
+
+ try (InputStream stream = url.openStream()) {
+ blackhole.consume(stream.available());
+ }
+ }
+
+ @Benchmark
+ public void getFileSizeUsingApacheCommon(Blackhole blackhole) {
+ File imageFile = new File("src/test/resources/size/sample_file_1.in");
+ long size = FileUtils.sizeOf(imageFile);
+ blackhole.consume(size);
+ }
+
+ @Benchmark
+ public void getFileSizeUsingFileChannel(Blackhole blackhole) throws IOException {
+ Path imageFilePath = Paths.get("src/test/resources/size/sample_file_1.in");
+ try (FileChannel imageFileChannel = FileChannel.open(imageFilePath)) {
+ long imageFileSize = imageFileChannel.size();
+ blackhole.consume(imageFileSize);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/size/JavaFileSizeUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/size/JavaFileSizeUnitTest.java
index 6b6197c7ce..d015f2602e 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/size/JavaFileSizeUnitTest.java
+++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/size/JavaFileSizeUnitTest.java
@@ -3,7 +3,10 @@ package com.baeldung.size;
import static org.junit.Assert.assertEquals;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -62,4 +65,24 @@ public class JavaFileSizeUnitTest {
final long length = file.length();
return length;
}
+
+ @Test
+ public void whenGetFileSizeUsingFileInputStream_thenCorrect() throws IOException {
+
+ try (FileInputStream fis = new FileInputStream(filePath)) {
+ long result = fis.getChannel().size();
+ assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, result);
+ }
+ }
+
+ @Test
+ public void whenGetFileSizeUsingUrlAndInputStream_thenCorrect() throws IOException {
+
+ File file = new File(filePath);
+ URL url = file.toURI().toURL();
+
+ try (InputStream stream = url.openStream()) {
+ assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, stream.available());
+ }
+ }
}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-6/README.md b/core-java-modules/core-java-lang-6/README.md
index 9ddd08d9ba..91c0e5212c 100644
--- a/core-java-modules/core-java-lang-6/README.md
+++ b/core-java-modules/core-java-lang-6/README.md
@@ -8,3 +8,4 @@ This module contains articles about core features in the Java language
- [What Is the Maximum Depth of the Java Call Stack?](https://www.baeldung.com/java-call-stack-max-depth)
- [Get a Random Element From a Set in Java](https://www.baeldung.com/java-set-draw-sample)
- [Stop Executing Further Code in Java](https://www.baeldung.com/java-stop-running-code)
+- [Using the Apache Commons Lang 3 for Comparing Objects in Java](https://www.baeldung.com/java-apache-commons-lang-3-compare-objects)
diff --git a/core-java-modules/core-java-lang-math-3/README.md b/core-java-modules/core-java-lang-math-3/README.md
index ef9c2ee4c4..37027970b6 100644
--- a/core-java-modules/core-java-lang-math-3/README.md
+++ b/core-java-modules/core-java-lang-math-3/README.md
@@ -12,4 +12,5 @@
- [Java Program to Print Pascal’s Triangle](https://www.baeldung.com/java-pascal-triangle)
- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency)
- [Clamp Function in Java](https://www.baeldung.com/java-clamp-function)
+- [Creating a Magic Square in Java](https://www.baeldung.com/java-magic-square)
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2)
diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java
index b6e7ac24f5..f2ddd65ff7 100644
--- a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java
+++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java
@@ -1,7 +1,5 @@
package com.baeldung.magicsquare;
-import org.junit.platform.commons.util.StringUtils;
-
import java.util.stream.IntStream;
public class MagicSquare {
diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md
deleted file mode 100644
index b2f7ece88a..0000000000
--- a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## Relevant Articles
-- [Creating a Magic Square in Java](https://www.baeldung.com/java-magic-square)
diff --git a/core-java-modules/core-java-lang-oop-others/README.md b/core-java-modules/core-java-lang-oop-others/README.md
index 4adfec86ef..ffd1d47f79 100644
--- a/core-java-modules/core-java-lang-oop-others/README.md
+++ b/core-java-modules/core-java-lang-oop-others/README.md
@@ -9,3 +9,4 @@ This module contains articles about Object Oriented Programming (OOP) in Java
- [Check If All the Variables of an Object Are Null](https://www.baeldung.com/java-check-all-variables-object-null)
- [Law of Demeter in Java](https://www.baeldung.com/java-demeter-law)
- [Java Interface Naming Conventions](https://www.baeldung.com/java-interface-naming-conventions)
+- [Difference Between Information Hiding and Encapsulation](https://www.baeldung.com/java-information-hiding-vs-encapsulation)
diff --git a/core-java-modules/core-java-numbers-6/README.md b/core-java-modules/core-java-numbers-6/README.md
index e3d5454d60..cf84e29710 100644
--- a/core-java-modules/core-java-numbers-6/README.md
+++ b/core-java-modules/core-java-numbers-6/README.md
@@ -6,4 +6,5 @@
- [How to Split an Integer Number Into Digits in Java](https://www.baeldung.com/java-integer-individual-digits)
- [Java Double vs. BigDecimal](https://www.baeldung.com/java-double-vs-bigdecimal)
- [Finding the Square Root of a BigInteger in Java](https://www.baeldung.com/java-find-square-root-biginteger)
+- [Truncate a Double to Two Decimal Places in Java](https://www.baeldung.com/java-double-round-two-decimal-places)
- More articles: [[<-- prev]](../core-java-numbers-5)
diff --git a/core-java-modules/core-java-numbers-conversions/README.md b/core-java-modules/core-java-numbers-conversions/README.md
index 27a07a5f8b..dead88f025 100644
--- a/core-java-modules/core-java-numbers-conversions/README.md
+++ b/core-java-modules/core-java-numbers-conversions/README.md
@@ -2,3 +2,5 @@
- [Convert a Number to a Letter in Java](https://www.baeldung.com/java-convert-number-to-letter)
- [Convert Long to BigDecimal in Java](https://www.baeldung.com/java-convert-long-bigdecimal)
- [Convert int to Long in Java](https://www.baeldung.com/java-convert-int-long)
+- [How To Convert Double To Float In Java](https://www.baeldung.com/java-convert-double-float)
+- [Converting from float to BigDecimal in Java](https://www.baeldung.com/java-convert-float-bigdecimal)
diff --git a/core-java-modules/core-java-os-2/README.md b/core-java-modules/core-java-os-2/README.md
index fa9f504184..c2f48f2854 100644
--- a/core-java-modules/core-java-os-2/README.md
+++ b/core-java-modules/core-java-os-2/README.md
@@ -3,5 +3,5 @@
This module contains articles about working with the operating system (OS) in Java
### Relevant Articles:
-
+- [How to Detect the Username Using Java](https://www.baeldung.com/java-get-username)
diff --git a/core-java-modules/core-java-os/README.md b/core-java-modules/core-java-os/README.md
index 81e67e4663..6d477de70a 100644
--- a/core-java-modules/core-java-os/README.md
+++ b/core-java-modules/core-java-os/README.md
@@ -14,6 +14,5 @@ This module contains articles about working with the operating system (OS) in Ja
- [How to Run a Shell Command in Java](http://www.baeldung.com/run-shell-command-in-java)
- [Taking Screenshots Using Java](https://www.baeldung.com/java-taking-screenshots)
- [Java Sound API – Capturing Microphone](https://www.baeldung.com/java-sound-api-capture-mic)
-- [How to Detect the Username Using Java](https://www.baeldung.com/java-get-username)
This module uses Java 9, so make sure to have the JDK 9 installed to run it.
diff --git a/core-java-modules/core-java-reflection-3/README.md b/core-java-modules/core-java-reflection-3/README.md
index d997aa22f1..023fb979e4 100644
--- a/core-java-modules/core-java-reflection-3/README.md
+++ b/core-java-modules/core-java-reflection-3/README.md
@@ -1,2 +1,2 @@
### Relevant Articles:
-- [Is Java Reflection Bad Practice?](https://www.baeldung.com/java-reflection-bad-practice)
+- [Is Java Reflection Bad Practice?](https://www.baeldung.com/java-reflection-benefits-drawbacks)
diff --git a/core-java-modules/core-java-security-4/pom.xml b/core-java-modules/core-java-security-4/pom.xml
index aae33f87d4..2b9809b749 100644
--- a/core-java-modules/core-java-security-4/pom.xml
+++ b/core-java-modules/core-java-security-4/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-security-4
core-java-security-4
diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java
index 8f36550bdc..c6530f4940 100644
--- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java
+++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java
@@ -6,19 +6,23 @@ import java.util.function.BinaryOperator;
import java.util.stream.Collector;
class SkippingCollector {
+
private static final BinaryOperator IGNORE_COMBINE = (a, b) -> a;
private final int skip;
private final List list = new ArrayList<>();
private int currentIndex = 0;
+
private SkippingCollector(int skip) {
this.skip = skip;
}
private void accept(String item) {
final int index = ++currentIndex % skip;
- if (index == 0)
+ if (index == 0) {
list.add(item);
+ }
}
+
private List getResult() {
return list;
}
diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java
deleted file mode 100644
index eb382367cc..0000000000
--- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.baeldung.skippingelements;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-public class SkippingElements {
-
- private SkippingElements() {
- }
-
- public static List skipNthElementInListWithFilter(List sourceList, int n) {
-return IntStream.range(0, sourceList.size())
- .filter(s -> (s + 1) % n == 0)
- .mapToObj(sourceList::get)
- .collect(Collectors.toList());
- }
-
- public static List skipNthElementInListWithIterate(List sourceList, int n) {
-int limit = sourceList.size() / n;
-return IntStream.iterate(n - 1, i -> (i + n))
- .limit(limit)
- .mapToObj(sourceList::get)
- .collect(Collectors.toList());
- }
-
- public static List skipNthElementInListWithSublist(List sourceList, int n) {
-int limit = sourceList.size() / n;
-return Stream.iterate(sourceList, s -> s.subList(n, s.size()))
- .limit(limit)
- .map(s -> s.get(n - 1))
- .collect(Collectors.toList());
- }
-
- public static List skipNthElementInListWithFor(List sourceList, int n) {
-List result = new ArrayList<>();
-for (int i = n - 1; i < sourceList.size(); i += n) {
- result.add(sourceList.get(i));
-}
-return result;
- }
-
- public static List skipNthElementInListWithIterator(Stream sourceStream, int n) {
-List result = new ArrayList<>();
-final Iterator iterator = sourceStream.iterator();
-int count = 0;
-while (iterator.hasNext()) {
- if (count % n == n - 1) {
- result.add(iterator.next());
- } else {
- iterator.next();
- }
- ++count;
-}
-return result;
- }
-
-public static List skipNthElementInStreamWithCollector(Stream sourceStream, int n) {
- return sourceStream.collect(SkippingCollector.collector(n));
-}
-
-}
diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java
index 2fd6adb0cf..92a13e62ab 100644
--- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java
+++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java
@@ -3,7 +3,11 @@ package com.baeldung.skippingelements;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -14,21 +18,22 @@ class SkippingElementsUnitTest {
private static Stream testSource() {
return Stream.of(
Arguments.of(
- List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
- List.of("Three", "Six", "Nine", "Twelve", "Fifteen", "Eighteen", "Twenty One", "Twenty Four", "Twenty Seven", "Thirty", "Thirty Three"),
+ List.of("Three", "Six", "Nine", "Twelve", "Fifteen", "Eighteen", "Twenty One", "Twenty Four", "Twenty Seven", "Thirty",
+ "Thirty Three"),
3),
Arguments.of(
- List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
List.of("Five", "Ten", "Fifteen", "Twenty", "Twenty Five", "Thirty"),
5),
Arguments.of(
- List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
@@ -38,29 +43,29 @@ class SkippingElementsUnitTest {
"Thirty One", "Thirty Two", "Thirty Three"),
1),
Arguments.of(
- List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Wednesday", "Saturday"),
3),
Arguments.of(
- List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Friday"),
5),
Arguments.of(
- List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
1),
Arguments.of(
- List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("March", "June", "September", "December"),
3),
Arguments.of(
- List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("May", "October"),
5),
Arguments.of(
- List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
@@ -70,45 +75,73 @@ class SkippingElementsUnitTest {
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInListWithFilterTestShouldFilterNthElement(List input, List expected, int n) {
- final List actual = SkippingElements.skipNthElementInListWithFilter(input, n);
+ void givenListSkipNthElementInListWithFilterTestShouldFilterNthElement(Stream input, List expected, int n) {
+ final List sourceList = input.collect(Collectors.toList());
+ final List actual = IntStream.range(0, sourceList.size())
+ .filter(s -> (s + 1) % n == 0)
+ .mapToObj(sourceList::get)
+ .collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInListWithIterateTestShouldFilterNthElement(List input, List expected, int n) {
- final List actual = SkippingElements.skipNthElementInListWithIterate(input, n);
+ void givenListSkipNthElementInListWithIterateTestShouldFilterNthElement(Stream input, List expected, int n) {
+ final List sourceList = input.collect(Collectors.toList());
+ int limit = sourceList.size() / n;
+ final List actual = IntStream.iterate(n - 1, i -> (i + n))
+ .limit(limit)
+ .mapToObj(sourceList::get)
+ .collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInListWithSublistTestShouldFilterNthElement(List input, List expected, int n) {
- final List actual = SkippingElements.skipNthElementInListWithSublist(input, n);
+ void givenListSkipNthElementInListWithSublistTestShouldFilterNthElement(Stream input, List expected, int n) {
+ final List sourceList = input.collect(Collectors.toList());
+ int limit = sourceList.size() / n;
+ final List actual = Stream.iterate(sourceList, s -> s.subList(n, s.size()))
+ .limit(limit)
+ .map(s -> s.get(n - 1))
+ .collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInListWithForTestShouldFilterNthElement(List input, List expected, int n) {
- final List actual = SkippingElements.skipNthElementInListWithFor(input, n);
+ void givenListSkipNthElementInListWithForTestShouldFilterNthElement(Stream input, List expected, int n) {
+ final List sourceList = input.collect(Collectors.toList());
+ List result = new ArrayList<>();
+ for (int i = n - 1; i < sourceList.size(); i += n) {
+ result.add(sourceList.get(i));
+ }
+ final List actual = result;
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInStreamWithIteratorTestShouldFilterNthElement(List input, List expected, int n) {
- final Stream inputStream = input.stream();
- final List actual = SkippingElements.skipNthElementInListWithIterator(inputStream, n);
+ void givenListSkipNthElementInStreamWithIteratorTestShouldFilterNthElement(Stream input, List expected, int n) {
+ List result = new ArrayList<>();
+ final Iterator iterator = input.iterator();
+ int count = 0;
+ while (iterator.hasNext()) {
+ if (count % n == n - 1) {
+ result.add(iterator.next());
+ } else {
+ iterator.next();
+ }
+ ++count;
+ }
+ final List actual = result;
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
- void givenListSkipNthElementInStreamWithCollectorShouldFilterNthElement(List input, List expected, int n) {
- final Stream inputStream = input.stream();
- final List actual = SkippingElements.skipNthElementInStreamWithCollector(inputStream, n);
+ void givenListSkipNthElementInStreamWithCollectorShouldFilterNthElement(Stream input, List expected, int n) {
+ final List actual = input.collect(SkippingCollector.collector(n));
assertEquals(expected, actual);
}
}
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-simple/README.md b/core-java-modules/core-java-streams-simple/README.md
index 94d74f4c49..4cbe32ce32 100644
--- a/core-java-modules/core-java-streams-simple/README.md
+++ b/core-java-modules/core-java-streams-simple/README.md
@@ -2,6 +2,10 @@
This module contains articles about Streams that are part of the Java Streams Ebook.
+### NOTE:
+
+Since this is a module tied to an e-book, it should **not** be moved or used to store the code for any further article.
+
### Relevant Articles
- [Introduction to Java 8 Streams](https://www.baeldung.com/java-8-streams-introduction)
@@ -11,4 +15,4 @@ This module contains articles about Streams that are part of the Java Streams Eb
- [The Difference Between map() and flatMap()](https://www.baeldung.com/java-difference-map-and-flatmap)
- [When to Use a Parallel Stream in Java](https://www.baeldung.com/java-when-to-use-parallel-stream)
- [Guide to Java 8 groupingBy Collector](https://www.baeldung.com/java-groupingby-collector)
-- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce)
\ No newline at end of file
+- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce)
diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml
index 536175acc2..507e830e8a 100644
--- a/core-java-modules/core-java-string-algorithms-3/pom.xml
+++ b/core-java-modules/core-java-string-algorithms-3/pom.xml
@@ -28,6 +28,11 @@
emoji-java
${emoji-java.version}
+
+ org.apache.commons
+ commons-text
+ ${apache-commons-text.version}
+
@@ -58,6 +63,7 @@
1.7
3.12.0
5.1.1
+ 1.10.0
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java
new file mode 100644
index 0000000000..7400745b2f
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java
@@ -0,0 +1,28 @@
+package com.baeldung.wrappingcharacterwise;
+
+import java.lang.IllegalArgumentException;
+import java.lang.String;
+import java.lang.StringBuilder;
+
+public class Wrapper {
+
+ public String wrapStringCharacterWise(String input, int n) {
+ StringBuilder stringBuilder = new StringBuilder(input);
+ int index = 0;
+ while(stringBuilder.length() > index + n) {
+ int lastLineReturn = stringBuilder.lastIndexOf("\n", index + n);
+ if (lastLineReturn > index) {
+ index = lastLineReturn;
+ } else {
+ index = stringBuilder.lastIndexOf(" ", index + n);
+ if (index == -1) {
+ throw new IllegalArgumentException("impossible to slice " + stringBuilder.substring(0, n));
+ }
+ stringBuilder.replace(index, index + 1, "\n");
+ index++;
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java
new file mode 100644
index 0000000000..8dcc323f7b
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.wrappingcharacterwise;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.commons.text.WordUtils;
+import org.junit.jupiter.api.Test;
+
+public class WrapperUnitTest {
+
+ Wrapper wrapper = new Wrapper();
+ String lineSeparator = System.lineSeparator();
+
+ @Test
+ void givenStringWithLessThanNCharacters_whenWrapStringCharacterWise_thenUnchanged() {
+ String input = "short sentence";
+ assertEquals(input, wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithMoreThanNCharacters_whenWrapStringCharacterWise_thenCorrectlyWrapped() {
+ String input = "Baeldung is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung is a\npopular website that\nprovides in-depth\ntutorials and\narticles on various\nprogramming and\nsoftware development\ntopics, primarily\nfocused on Java and\nrelated\ntechnologies.", wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithATooLongWord_whenWrapStringCharacterWise_thenThrows() {
+ String input = "The word straightforward has more than 10 characters";
+ assertThrows(IllegalArgumentException.class, () -> wrapper.wrapStringCharacterWise(input, 10));
+ }
+
+ @Test
+ void givenStringWithLineReturns_whenWrapStringCharacterWise_thenWrappedAccordingly() {
+ String input = "Baeldung\nis a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung\nis a popular\nwebsite that\nprovides in-depth\ntutorials and\narticles on various\nprogramming and\nsoftware development\ntopics, primarily\nfocused on Java and\nrelated\ntechnologies.", wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithLessThanNCharacters_whenWrap_thenUnchanged() {
+ String input = "short sentence";
+ assertEquals(input, WordUtils.wrap(input, 20));
+ }
+
+ @Test
+ void givenStringWithMoreThanNCharacters_whenWrap_thenCorrectlyWrapped() {
+ String input = "Baeldung is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung is a" + lineSeparator + "popular website that" + lineSeparator + "provides in-depth" + lineSeparator + "tutorials and" + lineSeparator + "articles on various" + lineSeparator + "programming and" + lineSeparator + "software development" + lineSeparator + "topics, primarily" + lineSeparator + "focused on Java and" + lineSeparator + "related" + lineSeparator + "technologies.", WordUtils.wrap(input, 20));
+ }
+
+ @Test
+ void givenStringWithATooLongWord_whenWrap_thenLongWordIsNotWrapped() {
+ String input = "The word straightforward has more than 10 characters";
+ assertEquals("The word" + lineSeparator + "straightforward" + lineSeparator + "has more" + lineSeparator + "than 10" + lineSeparator + "characters", WordUtils.wrap(input, 10));
+ }
+
+ @Test
+ void givenStringWithLineReturns_whenWrap_thenWrappedLikeThereWasNone() {
+ String input = "Baeldung" + lineSeparator + "is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung" + lineSeparator + "is a" + lineSeparator + "popular website that" + lineSeparator + "provides in-depth" + lineSeparator + "tutorials and" + lineSeparator + "articles on various" + lineSeparator + "programming and" + lineSeparator + "software development" + lineSeparator + "topics, primarily" + lineSeparator + "focused on Java and" + lineSeparator + "related" + lineSeparator + "technologies.", WordUtils.wrap(input, 20));
+ }
+
+}
diff --git a/core-java-modules/core-java-string-conversions-3/README.md b/core-java-modules/core-java-string-conversions-3/README.md
index 4b348dd555..4ec4771eea 100644
--- a/core-java-modules/core-java-string-conversions-3/README.md
+++ b/core-java-modules/core-java-string-conversions-3/README.md
@@ -2,3 +2,4 @@
- [Object.toString() vs String.valueOf()](https://www.baeldung.com/java-object-tostring-vs-string-valueof)
- [Convert String to Int Using Encapsulation](https://www.baeldung.com/java-encapsulation-convert-string-to-int)
- [HashMap with Multiple Values for the Same Key](https://www.baeldung.com/java-hashmap-multiple-values-per-key)
+- [Split Java String Into Key-Value Pairs](https://www.baeldung.com/java-split-string-map)
diff --git a/core-java-modules/core-java-string-conversions-3/pom.xml b/core-java-modules/core-java-string-conversions-3/pom.xml
index ddd5f7a497..b494a03fa7 100644
--- a/core-java-modules/core-java-string-conversions-3/pom.xml
+++ b/core-java-modules/core-java-string-conversions-3/pom.xml
@@ -23,4 +23,12 @@
-
\ No newline at end of file
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
diff --git a/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/objecttostring/Person.java b/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/objecttostring/Person.java
new file mode 100644
index 0000000000..61c0bd5711
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/objecttostring/Person.java
@@ -0,0 +1,34 @@
+package com.baeldung.objecttostring;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class Person {
+ private String name;
+ private int age;
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ @Override
+ public String toString() {
+ return "Person{name='" + name + "', age=" + age + '}';
+ }
+
+ public String toCustomString() {
+ return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
+ .append("name", name)
+ .append("age", age)
+ .toString();
+ }
+}
diff --git a/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/objecttostring/PersonUnitTest.java b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/objecttostring/PersonUnitTest.java
new file mode 100644
index 0000000000..7b61956dfc
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/objecttostring/PersonUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.objecttostring;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class PersonUnitTest {
+ @Test
+ public void givenObject_whenToString_thenConvert() {
+ Person person = new Person("Sarah", 28);
+ String expected = "Person{name='Sarah', age=28}";
+ String actual = person.toString();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenObject_whenValueOf_thenConvert() {
+ Person person = new Person("Sarah", 28);
+ String expected = "Person{name='Sarah', age=28}";
+ String actual = String.valueOf(person);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenObject_whenConcat_thenConvert() {
+ Person person = new Person("Sarah", 28);
+ String expected = "Person{name='Sarah', age=28}";
+ String actual = "" + person;
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenObject_whenToStringBuilder_thenConvert() {
+ Person person = new Person("Sarah", 28);
+ String expected = "{\"name\":\"Sarah\",\"age\":28}";
+ String actual = person.toCustomString();
+ assertEquals(expected, actual);
+ }
+}
diff --git a/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/centertext/CenteringTextUnitTest.java b/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/centertext/CenteringTextUnitTest.java
index ff53d8b3fa..a3f95b0181 100644
--- a/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/centertext/CenteringTextUnitTest.java
+++ b/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/centertext/CenteringTextUnitTest.java
@@ -3,6 +3,7 @@ package com.baeldung.centertext;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
+
import static org.junit.Assert.assertEquals;
public class CenteringTextUnitTest {
@@ -10,17 +11,16 @@ public class CenteringTextUnitTest {
@Test
public void givenTextAndTotalWidth_whenUsingStringFormat_thenTextIsCentered() {
String text = "Centered Text";
- int totalWidth = 20;
+ int totalWidth = 15;
int padding = (totalWidth - text.length()) / 2;
String centeredText = String.format("%" + padding + "s%s%" + padding + "s", "", text, "");
- String expectedCenteredText = " Centered Text ";
- Assert.assertEquals("Centered Text", expectedCenteredText, centeredText);
+ Assert.assertEquals(" Centered Text ", centeredText);
}
@Test
public void givenTextAndTotalWidth_whenCenterUsingStringBuilder_thenTextIsCentered() {
String text = "Centered Text";
- int width = 20;
+ int width = 15;
int padding = (width - text.length()) / 2;
StringBuilder centeredText = new StringBuilder();
for (int i = 0; i < padding; i++) {
@@ -31,17 +31,15 @@ public class CenteringTextUnitTest {
centeredText.append(" ");
}
String centeredTextString = centeredText.toString();
- String expectedCenteredText = " Centered Text ";
- Assert.assertEquals("Centered Text", expectedCenteredText, centeredTextString);
+ Assert.assertEquals(" Centered Text ", centeredTextString);
}
@Test
public void givenTextAndTotalWidth_whenUsingStringUtilsCenterMethod_thenTextIsCentered() {
String text = "Centered Text";
- int width = 20;
+ int width = 15;
String centeredText = StringUtils.center(text, width);
- String expectedCenteredText = StringUtils.center("Centered Text", width);
- assertEquals("Centered Text", expectedCenteredText, centeredText);
+ assertEquals(" Centered Text ", centeredText);
}
-}
\ No newline at end of file
+}
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index 8cfd67aed3..2152b90bcb 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -27,6 +27,11 @@
+
+
+
+
+
core-java-9-improvements
core-java-9-streams
core-java-9
@@ -188,6 +193,11 @@
core-java-collections-maps-6
core-java-records
core-java-9-jigsaw
+
+ core-java-collections-set
+ core-java-date-operations-1
+
+ core-java-httpclient
diff --git a/gradle-modules/gradle/gradle-fat-jar/build.gradle b/gradle-modules/gradle/gradle-fat-jar/build.gradle
index 6e2934194e..4c3d86d757 100644
--- a/gradle-modules/gradle/gradle-fat-jar/build.gradle
+++ b/gradle-modules/gradle/gradle-fat-jar/build.gradle
@@ -8,8 +8,10 @@ buildscript {
}
}
-apply plugin: 'java'
-apply plugin: 'com.github.johnrengelman.shadow'
+plugins {
+ id 'com.github.johnrengelman.shadow' version '7.1.2'
+ id 'java'
+}
repositories {
mavenCentral()
@@ -30,7 +32,7 @@ task customFatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.baeldung.fatjar.Application'
}
- baseName = 'all-in-one-jar'
+ archiveBaseName = 'all-in-one-jar'
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml
index d01c43dc90..3bf523bbfa 100644
--- a/jackson-simple/pom.xml
+++ b/jackson-simple/pom.xml
@@ -33,7 +33,7 @@
- 2.14.2
+ 2.15.2
17
diff --git a/jersey/README.md b/jersey/README.md
index 4c8c235be5..aa5a6a3b28 100644
--- a/jersey/README.md
+++ b/jersey/README.md
@@ -11,3 +11,4 @@ This module contains articles about Jersey.
- [Explore Jersey Request Parameters](https://www.baeldung.com/jersey-request-parameters)
- [Add a Header to a Jersey SSE Client Request](https://www.baeldung.com/jersey-sse-client-request-headers)
- [Exception Handling With Jersey](https://www.baeldung.com/java-exception-handling-jersey)
+- [@FormDataParam vs. @FormParam in Jersey](https://www.baeldung.com/jersey-formdataparam-vs-formparam)
diff --git a/libraries-apache-commons-2/README.md b/libraries-apache-commons-2/README.md
index 76105d6ea4..180c84b31c 100644
--- a/libraries-apache-commons-2/README.md
+++ b/libraries-apache-commons-2/README.md
@@ -4,4 +4,5 @@ This module contains articles about Apache Commons libraries.
### Relevant articles
- [Extracting a Tar File in Java](https://www.baeldung.com/java-extract-tar-file)
+- [Convert a String with Unicode Encoding to a String of Letters](https://www.baeldung.com/java-convert-string-unicode-encoding)
- More articles: [[<--prev]](../libraries-apache-commons)
diff --git a/lombok-modules/lombok/src/test/java/com/baeldung/lombok/builder/defaultvalue/BuilderWithDefaultValueUnitTest.java b/lombok-modules/lombok/src/test/java/com/baeldung/lombok/builder/defaultvalue/BuilderWithDefaultValueUnitTest.java
index d9184f605c..a03b262828 100644
--- a/lombok-modules/lombok/src/test/java/com/baeldung/lombok/builder/defaultvalue/BuilderWithDefaultValueUnitTest.java
+++ b/lombok-modules/lombok/src/test/java/com/baeldung/lombok/builder/defaultvalue/BuilderWithDefaultValueUnitTest.java
@@ -14,7 +14,7 @@ public class BuilderWithDefaultValueUnitTest {
}
@Test
- public void givenBuilderWithDefaultValue_NoArgsWorksAlso() {
+ public void givenBuilderWithDefaultValue_ThanNoArgsWorksAlso() {
Pojo build = new Pojo().toBuilder()
.build();
Pojo pojo = new Pojo();
diff --git a/parent-spring-6/pom.xml b/parent-spring-6/pom.xml
index 7b28afc9b1..7aaffb5483 100644
--- a/parent-spring-6/pom.xml
+++ b/parent-spring-6/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
parent-spring-6
0.0.1-SNAPSHOT
diff --git a/patterns-modules/design-patterns-creational-2/README.md b/patterns-modules/design-patterns-creational-2/README.md
index dc5b2a1861..b7fdb556d1 100644
--- a/patterns-modules/design-patterns-creational-2/README.md
+++ b/patterns-modules/design-patterns-creational-2/README.md
@@ -1,2 +1,3 @@
## Relevant Articles
- [The Factory Design Pattern in Java](https://www.baeldung.com/java-factory-pattern)
+- [Drawbacks of the Singleton Design Pattern](https://www.baeldung.com/java-patterns-singleton-cons)
diff --git a/patterns-modules/design-patterns-creational-2/pom.xml b/patterns-modules/design-patterns-creational-2/pom.xml
index fe79052a99..27c83c9eb7 100644
--- a/patterns-modules/design-patterns-creational-2/pom.xml
+++ b/patterns-modules/design-patterns-creational-2/pom.xml
@@ -12,4 +12,13 @@
1.0.0-SNAPSHOT
+
+
+ org.mockito
+ mockito-inline
+ ${mockito.version}
+ test
+
+
+
\ No newline at end of file
diff --git a/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/Logger.java b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/Logger.java
new file mode 100644
index 0000000000..31729c29f4
--- /dev/null
+++ b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/Logger.java
@@ -0,0 +1,38 @@
+package com.baeldung.singleton;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.time.LocalDateTime;
+
+public class Logger {
+ private static volatile Logger instance;
+
+ private PrintWriter fileWriter;
+
+ public static Logger getInstance() {
+ if (instance == null) {
+ synchronized (Logger.class) {
+ if (instance == null) {
+ instance = new Logger();
+ }
+ }
+ }
+ return instance;
+ }
+
+ private Logger() {
+ try {
+ fileWriter = new PrintWriter(new FileWriter("app.log"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void log(String message) {
+ String log = String.format("[%s]- %s", LocalDateTime.now(), message);
+ fileWriter.println(log);
+ fileWriter.flush();
+ }
+
+}
\ No newline at end of file
diff --git a/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/SingletonDemo.java b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/SingletonDemo.java
new file mode 100644
index 0000000000..2ebd6c8ad4
--- /dev/null
+++ b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/singleton/SingletonDemo.java
@@ -0,0 +1,12 @@
+package com.baeldung.singleton;
+
+public class SingletonDemo {
+
+ public int sum(int a, int b) {
+ int result = a + b;
+ Logger logger = Logger.getInstance();
+ logger.log("The sum is " + result);
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/singleton/SingletonUnitTest.java b/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/singleton/SingletonUnitTest.java
new file mode 100644
index 0000000000..d4154d9396
--- /dev/null
+++ b/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/singleton/SingletonUnitTest.java
@@ -0,0 +1,35 @@
+package com.baeldung.singleton;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+
+class SingletonUnitTest {
+
+ @Test
+ void givenTwoValues_whenSum_thenReturnCorrectResult() {
+ SingletonDemo singletonDemo = new SingletonDemo();
+ int result = singletonDemo.sum(12, 4);
+ Assertions.assertEquals(16, result);
+ }
+
+ @Test
+ void givenMockedLogger_whenSum_thenReturnCorrectResult() {
+ Logger logger = mock(Logger.class);
+
+ try (MockedStatic loggerMockedStatic = mockStatic(Logger.class)) {
+ loggerMockedStatic.when(Logger::getInstance).thenReturn(logger);
+ doNothing().when(logger).log(any());
+
+ SingletonDemo singletonDemo = new SingletonDemo();
+ int result = singletonDemo.sum(12, 4);
+ Assertions.assertEquals(16, result);
+ }
+ }
+
+}
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 7787e0bda8..62c7fd1049 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -35,7 +35,7 @@
hibernate-queries
hibernate-enterprise
influxdb
- java-cassandra
+ java-cassandra
java-cockroachdb
java-jdbi
java-jpa
@@ -110,7 +110,6 @@
spring-mybatis
spring-persistence-simple
spring-data-yugabytedb
-
fauna
spring-data-rest
java-mongodb
diff --git a/persistence-modules/spring-boot-persistence-h2/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml
index f643db2260..3c4bf888b3 100644
--- a/persistence-modules/spring-boot-persistence-h2/pom.xml
+++ b/persistence-modules/spring-boot-persistence-h2/pom.xml
@@ -11,9 +11,9 @@
com.baeldung
- parent-boot-2
+ parent-boot-3
0.0.1-SNAPSHOT
- ../../parent-boot-2
+ ../../parent-boot-3
@@ -44,12 +44,19 @@
db-util
${db-util.version}
+
+
+
+ org.hibernate.orm
+ hibernate-core
+ 6.3.1.Final
+
com.baeldung.h2db.demo.server.SpringBootApp
- 1.0.4
+ 1.0.7
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2/exceptions/models/User.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2/exceptions/models/User.java
index e54e725fd0..e1ae3c7cf0 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2/exceptions/models/User.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2/exceptions/models/User.java
@@ -1,7 +1,7 @@
package com.baeldung.h2.exceptions.models;
-import javax.persistence.Entity;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
@Entity
public class User {
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
index 7402312e1c..3416cba154 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
@@ -3,15 +3,15 @@ package com.baeldung.h2db.demo.client;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
-import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
+import jakarta.annotation.PostConstruct;
+
@SpringBootApplication
@ComponentScan("com.baeldung.h2db.demo.client")
public class ClientSpringBootApp {
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
index e75b42a934..2a1eb66b22 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
@@ -3,7 +3,7 @@ package com.baeldung.h2db.demo.server;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
import org.h2.tools.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/Document.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/Document.java
index 9d69e7eb58..e737722ad4 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/Document.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/Document.java
@@ -1,13 +1,14 @@
package com.baeldung.h2db.lazy_load_no_trans.entity;
+import jakarta.persistence.Column;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Immutable;
-import javax.persistence.Entity;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
@Entity
@Getter
@@ -22,5 +23,6 @@ public class Document {
private String title;
+ @Column(name="user_id")
private Long userId;
}
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/User.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/User.java
index ae9cb9e4e8..b46903e589 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/User.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/lazy_load_no_trans/entity/User.java
@@ -8,10 +8,10 @@ import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Immutable;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.OneToMany;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/notnull/models/Item.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/notnull/models/Item.java
index d2c4015b86..d36c763f0f 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/notnull/models/Item.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/notnull/models/Item.java
@@ -1,9 +1,10 @@
package com.baeldung.h2db.notnull.models;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.validation.constraints.NotNull;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.validation.constraints.NotNull;
+
import java.math.BigDecimal;
@Entity
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java
index d6edab9421..c8bec1e908 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/Country.java
@@ -1,9 +1,9 @@
package com.baeldung.h2db.springboot.models;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
import java.util.Objects;
@Table(name = "countries")
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql
index 2b4aa92542..7031d3ac02 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data-trans.sql
@@ -4,9 +4,9 @@ insert into "user" values (103, 'user3', 'comment3');
insert into "user" values (104, 'user4', 'comment4');
insert into "user" values (105, 'user5', 'comment5');
-insert into "document" values (1, 'doc1', 101);
-insert into "document" values (2, 'doc2', 101);
-insert into "document" values (3, 'doc3', 101);
-insert into "document" values (4, 'doc4', 101);
-insert into "document" values (5, 'doc5', 102);
-insert into "document" values (6, 'doc6', 102);
\ No newline at end of file
+insert into "document" ("id","title","user_id") values (1, 'doc1', 101);
+insert into "document" ("id","title","user_id") values (2, 'doc2', 101);
+insert into "document" ("id","title","user_id") values (3, 'doc3', 101);
+insert into "document" ("id","title","user_id") values (4, 'doc4', 101);
+insert into "document" ("id","title","user_id") values (5, 'doc5', 102);
+insert into "document" ("id","title","user_id") values (6, 'doc6', 102);
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/h2db/notnull/ItemIntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/h2db/notnull/ItemIntegrationTest.java
index 0e2e5e3319..1213df4780 100644
--- a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/h2db/notnull/ItemIntegrationTest.java
+++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/h2db/notnull/ItemIntegrationTest.java
@@ -2,16 +2,17 @@ package com.baeldung.h2db.notnull;
import com.baeldung.h2db.notnull.daos.ItemRepository;
import com.baeldung.h2db.notnull.models.Item;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
-import javax.validation.ConstraintViolationException;
-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import jakarta.validation.ConstraintViolationException;
+
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NotNullVsNullableApplication.class)
public class ItemIntegrationTest {
@@ -21,8 +22,8 @@ public class ItemIntegrationTest {
@Test
public void shouldNotAllowToPersistNullItemsPrice() {
- assertThatThrownBy(() -> itemRepository.save(new Item()))
- .hasRootCauseInstanceOf(ConstraintViolationException.class)
- .hasStackTraceContaining("must not be null");
+ assertThatThrownBy(() -> itemRepository.save(new Item())).hasRootCauseInstanceOf(ConstraintViolationException.class)
+ .hasStackTraceContaining("propertyPath=price")
+ .hasStackTraceContaining("null");
}
}
diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml
index a353f60ad2..6535b9ac4b 100644
--- a/persistence-modules/spring-data-elasticsearch/pom.xml
+++ b/persistence-modules/spring-data-elasticsearch/pom.xml
@@ -19,18 +19,18 @@
spring-data-elasticsearch
${spring-data-elasticsearch.version}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
org.elasticsearch.client
@@ -47,6 +47,7 @@
spring-boot-autoconfigure
+
@@ -55,6 +56,7 @@
+
5.1.2
8.9.0
diff --git a/persistence-modules/spring-data-jpa-query-2/pom.xml b/persistence-modules/spring-data-jpa-query-2/pom.xml
index c74c35c37b..1282d1d8a0 100644
--- a/persistence-modules/spring-data-jpa-query-2/pom.xml
+++ b/persistence-modules/spring-data-jpa-query-2/pom.xml
@@ -1,16 +1,16 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
spring-data-jpa-query-2
spring-data-jpa-query-2
com.baeldung
- parent-boot-2
+ parent-boot-3
0.0.1-SNAPSHOT
- ../../parent-boot-2
+ ../../parent-boot-3
@@ -38,6 +38,7 @@
mysql
mysql-connector-java
+ 3.1.12
com.google.guava
@@ -50,12 +51,19 @@
${tomcat-dbcp.version}
- org.hibernate
+ org.hibernate.orm
hibernate-core
+ 6.3.1.Final
- org.hibernate
+ org.hibernate.orm
hibernate-envers
+ 6.3.1.Final
+
+
+ org.apache.commons
+ commons-lang3
+ 3.13.0
org.springframework
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
index f4a9b8a678..70349a664d 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
@@ -1,6 +1,6 @@
package com.baeldung.hibernate.fetching.model;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.io.Serializable;
import java.sql.Date;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
index 9fda4c43bb..d273f942a5 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
@@ -1,6 +1,6 @@
package com.baeldung.hibernate.fetching.model;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
index a78eaa4ac0..6d18b2517c 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
@@ -1,6 +1,6 @@
package com.baeldung.hibernate.fetching.model;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
index 79bdd86658..d43ee46844 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
@@ -3,12 +3,12 @@ package com.baeldung.persistence.dao.common;
import java.io.Serializable;
import java.util.List;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
public class AbstractJpaDao extends AbstractDao implements IOperations {
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java
index 0ceb2d5626..15a4fdb3ca 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java
@@ -3,29 +3,29 @@ package com.baeldung.persistence.model;
import com.google.common.collect.Sets;
import org.hibernate.annotations.OrderBy;
import org.hibernate.envers.Audited;
-import org.jboss.logging.Logger;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityListeners;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.PrePersist;
-import javax.persistence.PreRemove;
-import javax.persistence.PreUpdate;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.PrePersist;
+import jakarta.persistence.PreRemove;
+import jakarta.persistence.PreUpdate;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
+import java.util.logging.Logger;
@Entity
@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b")
@@ -33,7 +33,7 @@ import java.util.Set;
@EntityListeners(AuditingEntityListener.class)
public class Bar implements Serializable {
- private static final Logger LOGGER = Logger.getLogger(Bar.class);
+ private static final Logger LOGGER = Logger.getLogger(Bar.class.toString());
public enum OPERATION {
INSERT, UPDATE, DELETE;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java
index 19cfb2e237..9a1f95c019 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java
@@ -2,10 +2,10 @@ package com.baeldung.persistence.model;
import java.io.Serializable;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.OneToOne;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToOne;
@Entity
public class Child implements Serializable {
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java
index ac79653b2b..b7e8adba42 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java
@@ -2,20 +2,20 @@ package com.baeldung.persistence.model;
import java.io.Serializable;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedNativeQueries;
-import javax.persistence.NamedNativeQuery;
-import javax.persistence.NamedStoredProcedureQuery;
-import javax.persistence.ParameterMode;
-import javax.persistence.StoredProcedureParameter;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.NamedNativeQueries;
+import jakarta.persistence.NamedNativeQuery;
+import jakarta.persistence.NamedStoredProcedureQuery;
+import jakarta.persistence.ParameterMode;
+import jakarta.persistence.StoredProcedureParameter;
import org.hibernate.envers.Audited;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java
index fa6948990b..4149a0b883 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java
@@ -2,12 +2,12 @@ package com.baeldung.persistence.model;
import java.io.Serializable;
-import javax.persistence.CascadeType;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToOne;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.OneToOne;
@Entity
public class Parent implements Serializable {
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java
index 6a95a7acf5..3766639975 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java
@@ -1,8 +1,8 @@
package com.baeldung.persistence.model;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
@Entity
public class Person {
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java
index 179dbf2ae7..648b06cf5f 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/User.java
@@ -1,6 +1,6 @@
package com.baeldung.spring.data.jpa.query;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java
index 033f61fdd3..54cea74e04 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/UserRepositoryCustomImpl.java
@@ -1,8 +1,8 @@
package com.baeldung.spring.data.jpa.query;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.criteria.*;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
index f591773cde..d9ab75af2c 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
@@ -4,8 +4,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
import org.junit.After;
import org.junit.AfterClass;
@@ -30,15 +30,15 @@ import com.baeldung.spring.config.PersistenceTestConfig;
@ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class JPABarAuditIntegrationTest {
- private static Logger logger = LoggerFactory.getLogger(JPABarAuditIntegrationTest.class);
+ private static final Logger logger = LoggerFactory.getLogger(JPABarAuditIntegrationTest.class);
@BeforeClass
- public static void setUpBeforeClass() throws Exception {
+ public static void setUpBeforeClass() {
logger.info("setUpBeforeClass()");
}
@AfterClass
- public static void tearDownAfterClass() throws Exception {
+ public static void tearDownAfterClass(){
logger.info("tearDownAfterClass()");
}
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
index 0603067810..0d22562a93 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
@@ -3,8 +3,8 @@ package com.baeldung.persistence.audit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
import org.junit.After;
import org.junit.AfterClass;
@@ -29,7 +29,7 @@ import com.baeldung.spring.config.PersistenceTestConfig;
@ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class SpringDataJPABarAuditIntegrationTest {
- private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class);
+ private static final Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class);
@BeforeClass
public static void setUpBeforeClass() throws Exception {
@@ -37,7 +37,7 @@ public class SpringDataJPABarAuditIntegrationTest {
}
@AfterClass
- public static void tearDownAfterClass() throws Exception {
+ public static void tearDownAfterClass(){
logger.info("tearDownAfterClass()");
}
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
index a7763bb0f8..92a9d8e2ec 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
@@ -17,7 +17,7 @@ public class FooFixtures {
private static final Logger LOGGER = LoggerFactory.getLogger(FooFixtures.class);
- private SessionFactory sessionFactory;
+ private final SessionFactory sessionFactory;
public FooFixtures(final SessionFactory sessionFactory) {
super();
@@ -28,8 +28,8 @@ public class FooFixtures {
// API
public void createBars() {
- Session session = null;
- Transaction tx = null;
+ Session session;
+ Transaction tx;
session = sessionFactory.openSession();
tx = session.getTransaction();
try {
@@ -39,13 +39,13 @@ public class FooFixtures {
bar.setName("Bar_" + i);
final Foo foo = new Foo("Foo_" + (i + 120));
foo.setBar(bar);
- session.save(foo);
+ session.persist(foo);
final Foo foo2 = new Foo(null);
if (i % 2 == 0) {
foo2.setName("LuckyFoo" + (i + 120));
}
foo2.setBar(bar);
- session.save(foo2);
+ session.persist(foo2);
bar.getFooSet().add(foo);
bar.getFooSet().add(foo2);
session.merge(bar);
@@ -53,16 +53,12 @@ public class FooFixtures {
tx.commit();
session.flush();
} catch (final HibernateException he) {
- if (tx != null) {
- tx.rollback();
- }
+ tx.rollback();
LOGGER.error("Not able to open session", he);
} catch (final Exception e) {
LOGGER.error(e.getLocalizedMessage(), e);
} finally {
- if (session != null) {
- session.close();
- }
+ session.close();
}
}
@@ -86,23 +82,18 @@ public class FooFixtures {
try {
tx.begin();
for (final Foo foo : fooList) {
-
- session.save(foo.getBar());
- session.save(foo);
+ session.persist(foo.getBar());
+ session.persist(foo);
}
tx.commit();
session.flush();
} catch (final HibernateException he) {
- if (tx != null) {
- tx.rollback();
- }
+ tx.rollback();
LOGGER.error("Not able to open session", he);
} catch (final Exception e) {
LOGGER.error(e.getLocalizedMessage(), e);
} finally {
- if (session != null) {
- session.close();
- }
+ session.close();
}
}
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
index fd7bc4aabf..528eed9d8d 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
@@ -1,19 +1,19 @@
package com.baeldung.persistence.hibernate;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.lessThan;
-import static org.junit.Assert.assertThat;
import java.util.List;
-import org.hibernate.Criteria;
-import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
-import org.hibernate.criterion.Projections;
+import org.hibernate.query.Query;
+import org.hibernate.query.SelectionQuery;
+import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -28,6 +28,8 @@ import com.baeldung.persistence.service.IFooService;
import com.baeldung.spring.config.PersistenceTestConfig;
import com.google.common.collect.Lists;
+import jakarta.persistence.criteria.CriteriaQuery;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class FooPaginationPersistenceIntegrationTest {
@@ -40,8 +42,6 @@ public class FooPaginationPersistenceIntegrationTest {
private Session session;
- // tests
-
@Before
public final void before() {
final int minimalNumberOfEntities = 25;
@@ -59,20 +59,17 @@ public class FooPaginationPersistenceIntegrationTest {
session.close();
}
- // tests
-
@Test
public final void whenContextIsBootstrapped_thenNoExceptions() {
//
}
- @SuppressWarnings("unchecked")
@Test
public final void whenRetrievingPaginatedEntities_thenCorrectSize() {
final int pageNumber = 1;
final int pageSize = 10;
- final Query query = session.createQuery("From Foo");
+ final Query query = session.createQuery("From Foo",Foo.class);
query.setFirstResult((pageNumber - 1) * pageSize);
query.setMaxResults(pageSize);
final List fooList = query.list();
@@ -80,19 +77,18 @@ public class FooPaginationPersistenceIntegrationTest {
assertThat(fooList, hasSize(pageSize));
}
- @SuppressWarnings("unchecked")
@Test
public final void whenRetrievingAllPages_thenCorrect() {
int pageNumber = 1;
final int pageSize = 10;
final String countQ = "Select count (f.id) from Foo f";
- final Query countQuery = session.createQuery(countQ);
+ final Query countQuery = session.createQuery(countQ, Long.class);
final Long countResult = (Long) countQuery.uniqueResult();
final List fooList = Lists.newArrayList();
int totalEntities = 0;
- final Query query = session.createQuery("From Foo");
+ final Query query = session.createQuery("From Foo", Foo.class);
while (totalEntities < countResult) {
query.setFirstResult((pageNumber - 1) * pageSize);
query.setMaxResults(pageSize);
@@ -102,17 +98,16 @@ public class FooPaginationPersistenceIntegrationTest {
}
}
- @SuppressWarnings("unchecked")
@Test
public final void whenRetrievingLastPage_thenCorrectSize() {
final int pageSize = 10;
final String countQ = "Select count (f.id) from Foo f";
- final Query countQuery = session.createQuery(countQ);
- final Long countResults = (Long) countQuery.uniqueResult();
+ final Query countQuery = session.createQuery(countQ, Long.class);
+ final Long countResults = countQuery.uniqueResult();
final int lastPageNumber = (int) (Math.ceil(countResults / pageSize));
- final Query selectQuery = session.createQuery("From Foo");
+ final Query selectQuery = session.createQuery("From Foo",Foo.class);
selectQuery.setFirstResult((lastPageNumber - 1) * pageSize);
selectQuery.setMaxResults(pageSize);
final List lastPage = selectQuery.list();
@@ -126,9 +121,9 @@ public class FooPaginationPersistenceIntegrationTest {
public final void givenUsingTheScrollableApi_whenRetrievingPaginatedData_thenCorrect() {
final int pageSize = 10;
final String hql = "FROM Foo f order by f.name";
- final Query query = session.createQuery(hql);
+ final Query query = session.createQuery(hql,Foo.class);
- final ScrollableResults resultScroll = query.scroll(ScrollMode.FORWARD_ONLY);
+ final ScrollableResults resultScroll = query.scroll(ScrollMode.FORWARD_ONLY);
// resultScroll.last();
// final int totalResults = resultScroll.getRowNumber() + 1;
@@ -138,7 +133,7 @@ public class FooPaginationPersistenceIntegrationTest {
final List fooPage = Lists.newArrayList();
int i = 0;
while (pageSize > i++) {
- fooPage.add((Foo) resultScroll.get(0));
+ fooPage.add((Foo) resultScroll.get());
if (!resultScroll.next()) {
break;
}
@@ -147,36 +142,42 @@ public class FooPaginationPersistenceIntegrationTest {
assertThat(fooPage, hasSize(lessThan(10 + 1)));
}
- @SuppressWarnings("unchecked")
@Test
public final void givenUsingTheCriteriaApi_whenRetrievingFirstPage_thenCorrect() {
final int pageSize = 10;
- final Criteria criteria = session.createCriteria(Foo.class);
- criteria.setFirstResult(0);
- criteria.setMaxResults(pageSize);
- final List firstPage = criteria.list();
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+
+ SelectionQuery query = session.createQuery(selectQuery);
+ query.setFirstResult(0);
+ query.setMaxResults(pageSize);
+ final List firstPage = query.list();
assertThat(firstPage, hasSize(pageSize));
}
- @SuppressWarnings("unchecked")
@Test
public final void givenUsingTheCriteriaApi_whenRetrievingPaginatedData_thenCorrect() {
- final Criteria criteriaCount = session.createCriteria(Foo.class);
- criteriaCount.setProjection(Projections.rowCount());
- final Long count = (Long) criteriaCount.uniqueResult();
+
+ HibernateCriteriaBuilder qb = session.getCriteriaBuilder();
+ CriteriaQuery cq = qb.createQuery(Long.class);
+ cq.select(qb.count(cq.from(Foo.class)));
+ final Long count = session.createQuery(cq).getSingleResult();
int pageNumber = 1;
final int pageSize = 10;
final List fooList = Lists.newArrayList();
- final Criteria criteria = session.createCriteria(Foo.class);
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+ SelectionQuery query = session.createQuery(selectQuery);
+
int totalEntities = 0;
while (totalEntities < count.intValue()) {
- criteria.setFirstResult((pageNumber - 1) * pageSize);
- criteria.setMaxResults(pageSize);
- fooList.addAll(criteria.list());
+ query.setFirstResult((pageNumber - 1) * pageSize);
+ query.setMaxResults(pageSize);
+ fooList.addAll(query.list());
totalEntities = fooList.size();
pageNumber++;
}
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
index 6078eb3af0..7e2d23da96 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
@@ -2,15 +2,17 @@ package com.baeldung.persistence.hibernate;
import static org.junit.Assert.assertNull;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
-import org.hibernate.Criteria;
-import org.hibernate.NullPrecedence;
-import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
-import org.hibernate.criterion.Order;
+import org.hibernate.query.NullPrecedence;
+import org.hibernate.query.Order;
+import org.hibernate.query.Query;
+import org.hibernate.query.SortDirection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -26,6 +28,8 @@ import com.baeldung.persistence.model.Bar;
import com.baeldung.persistence.model.Foo;
import com.baeldung.spring.config.PersistenceTestConfig;
+import jakarta.persistence.criteria.CriteriaQuery;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceTestConfig.class }, loader = AnnotationConfigContextLoader.class)
@SuppressWarnings("unchecked")
@@ -91,7 +95,7 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() {
final String hql = "FROM Foo f ORDER BY f.name ASC";
- final Query query = session.createQuery(hql);
+ Query query = session.createQuery(hql, Foo.class);
final List fooList = query.list();
for (final Foo foo : fooList) {
LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId());
@@ -101,7 +105,7 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenHQlSortingByMultipleAttributes_thenSortedResults() {
final String hql = "FROM Foo f ORDER BY f.name, f.id";
- final Query query = session.createQuery(hql);
+ Query query = session.createQuery(hql, Foo.class);
final List fooList = query.list();
for (final Foo foo : fooList) {
LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId());
@@ -111,7 +115,7 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() {
final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
- final Query query = session.createQuery(hql);
+ Query query = session.createQuery(hql, Foo.class);
final List fooList = query.list();
for (final Foo foo : fooList) {
LOGGER.debug("Name: {}, Id: {}", foo.getName(), foo.getId());
@@ -120,9 +124,12 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() {
- final Criteria criteria = session.createCriteria(Foo.class, "FOO");
- criteria.addOrder(Order.asc("id"));
- final List fooList = criteria.list();
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+ Query query = session.createQuery(selectQuery);
+
+ query.setOrder(Collections.singletonList(Order.asc(Foo.class,"id")));
+ final List fooList = query.list();
for (final Foo foo : fooList) {
LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName());
}
@@ -130,10 +137,16 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() {
- final Criteria criteria = session.createCriteria(Foo.class, "FOO");
- criteria.addOrder(Order.asc("name"));
- criteria.addOrder(Order.asc("id"));
- final List fooList = criteria.list();
+
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+ Query query = session.createQuery(selectQuery);
+
+ List> orderBy = new ArrayList<>(2);
+ orderBy.add(Order.asc(Foo.class,"name"));
+ orderBy.add(Order.asc(Foo.class,"id"));
+ query.setOrder(orderBy);
+ final List fooList = query.list();
for (final Foo foo : fooList) {
LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName());
}
@@ -141,9 +154,15 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() {
- final Criteria criteria = session.createCriteria(Foo.class, "FOO");
- criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));
- final List fooList = criteria.list();
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+ Query query = session.createQuery(selectQuery);
+
+ List> orderBy = new ArrayList<>(2);
+ orderBy.add(Order.by(Foo.class,"name", SortDirection.ASCENDING, NullPrecedence.LAST));
+ query.setOrder(orderBy);
+
+ final List fooList = query.list();
assertNull(fooList.get(fooList.toArray().length - 1).getName());
for (final Foo foo : fooList) {
LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName());
@@ -152,9 +171,15 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() {
- final Criteria criteria = session.createCriteria(Foo.class, "FOO");
- criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));
- final List fooList = criteria.list();
+ CriteriaQuery selectQuery = session.getCriteriaBuilder().createQuery(Foo.class);
+ selectQuery.from(Foo.class);
+ Query query = session.createQuery(selectQuery);
+
+ List> orderBy = new ArrayList<>(2);
+ orderBy.add(Order.by(Foo.class,"name", SortDirection.ASCENDING, NullPrecedence.FIRST));
+ query.setOrder(orderBy);
+
+ final List fooList = query.list();
assertNull(fooList.get(0).getName());
for (final Foo foo : fooList) {
LOGGER.debug("Id: {}, FirstName: {}", foo.getId(), foo.getName());
@@ -164,7 +189,7 @@ public class FooSortingPersistenceIntegrationTest {
@Test
public final void whenSortingBars_thenBarsWithSortedFoos() {
final String hql = "FROM Bar b ORDER BY b.id";
- final Query query = session.createQuery(hql);
+ final Query query = session.createQuery(hql, Bar.class);
final List barList = query.list();
for (final Bar bar : barList) {
final Set fooSet = bar.getFooSet();
diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java
index f6dedfc6de..d8216fc072 100644
--- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java
+++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java
@@ -5,14 +5,14 @@ import static org.junit.Assert.assertEquals;
import java.util.List;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.StoredProcedureQuery;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.StoredProcedureQuery;
-import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.exception.SQLGrammarException;
+import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
@@ -59,22 +59,22 @@ public class FooStoredProceduresLiveTest {
private boolean getFoosByNameExists() {
try {
- Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
+ Query sqlQuery = session.createNativeQuery("CALL GetFoosByName()",Foo.class);
sqlQuery.list();
return true;
} catch (SQLGrammarException e) {
- LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e);
+ LOGGER.error("WARNING : GetFoosByName() Procedure may be missing ", e);
return false;
}
}
private boolean getAllFoosExists() {
try {
- Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
+ Query sqlQuery = session.createNativeQuery("CALL GetAllFoos()",Foo.class);
sqlQuery.list();
return true;
} catch (SQLGrammarException e) {
- LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e);
+ LOGGER.error("WARNING : GetAllFoos() Procedure may be missing ", e);
return false;
}
}
@@ -90,9 +90,9 @@ public class FooStoredProceduresLiveTest {
fooService.create(new Foo(randomAlphabetic(6)));
- // Stored procedure getAllFoos using createSQLQuery
- Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
- @SuppressWarnings("unchecked")
+ // Stored procedure getAllFoos using createQuery
+ Query sqlQuery = session.createNativeQuery("CALL GetAllFoos()", Foo.class);
+
List allFoos = sqlQuery.list();
for (Foo foo : allFoos) {
LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName());
@@ -100,8 +100,8 @@ public class FooStoredProceduresLiveTest {
assertEquals(allFoos.size(), fooService.findAll().size());
// Stored procedure getAllFoos using a Named Query
- Query namedQuery = session.getNamedQuery("callGetAllFoos");
- @SuppressWarnings("unchecked")
+ Query namedQuery = session.createNamedQuery("callGetAllFoos", Foo.class);
+
List allFoos2 = namedQuery.list();
for (Foo foo : allFoos2) {
LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName());
@@ -110,6 +110,7 @@ public class FooStoredProceduresLiveTest {
StoredProcedureQuery spQuery =
entityManager.createNamedStoredProcedureQuery("GetAllFoos");
+ @SuppressWarnings("unchecked")
List allFoos3 = spQuery.getResultList();
for (Foo foo : allFoos3) {
LOGGER.info("getAllFoos() StoredProcedureQuery result : {}", foo.getName());
@@ -124,16 +125,16 @@ public class FooStoredProceduresLiveTest {
fooService.create(new Foo("NewFooName"));
// Stored procedure getFoosByName using createSQLQuery()
- Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)").addEntity(Foo.class).setParameter("fooName", "NewFooName");
- @SuppressWarnings("unchecked")
+ Query sqlQuery = session.createNativeQuery("CALL GetFoosByName(:fooName)", Foo.class).setParameter("fooName", "NewFooName");
+
List allFoosByName = sqlQuery.list();
for (Foo foo : allFoosByName) {
LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString());
}
// Stored procedure getFoosByName using getNamedQuery()
- Query namedQuery = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName");
- @SuppressWarnings("unchecked")
+ Query namedQuery = session.createQuery("callGetFoosByName", Foo.class).setParameter("fooName", "NewFooName");
+
List allFoosByName2 = namedQuery.list();
for (Foo foo : allFoosByName2) {
LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString());
@@ -142,6 +143,7 @@ public class FooStoredProceduresLiveTest {
StoredProcedureQuery spQuery = entityManager.
createNamedStoredProcedureQuery("GetFoosByName")
.setParameter("fooName", "NewFooName");
+ @SuppressWarnings("unchecked")
List allFoosByName3 = spQuery.getResultList();
assertEquals(1, allFoosByName3.size());
for (Foo foo : allFoosByName3) {
diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/entity/Library.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/entity/Library.java
index 04c0ad5e0a..724adc3aad 100644
--- a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/entity/Library.java
+++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/listrepositories/entity/Library.java
@@ -19,7 +19,7 @@ public class Library {
private List addresses = new ArrayList<>();
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
- @CollectionTable(name = "book", joinColumns = @JoinColumn(name = "library_id"))
+ @CollectionTable(name = "books", joinColumns = @JoinColumn(name = "library_id"))
@Column(name = "book", nullable = false)
private List books = new ArrayList<>();
diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-repo-3/src/main/resources/application.properties
index cd6dbe3994..37f37d548d 100644
--- a/persistence-modules/spring-data-jpa-repo-3/src/main/resources/application.properties
+++ b/persistence-modules/spring-data-jpa-repo-3/src/main/resources/application.properties
@@ -1,5 +1,5 @@
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=none
-
+spring.jpa.generate-ddl=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java
index 8f34e43e3f..9ea865c04f 100644
--- a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/listrepositories/repository/BookPagingAndSortingRepositoryIntegrationTest.java
@@ -21,13 +21,13 @@ public class BookPagingAndSortingRepositoryIntegrationTest {
@Test
public void givenDbContainsBooks_whenfindBooksByAuthor_thenReturnBooksByAuthor() {
- Book book1 = new Book("Spring Data", "John Doe", "1234567890");
- Book book2 = new Book("Spring Data 2", "John Doe", "1234567891");
- Book book3 = new Book("Spring Data 3", "John Doe", "1234567892");
+ Book book1 = new Book("Spring Data", "John Miller", "1234567890");
+ Book book2 = new Book("Spring Data 2", "John Miller", "1234567891");
+ Book book3 = new Book("Spring Data 3", "John Miller", "1234567892");
bookPagingAndSortingRepository.saveAll(Arrays.asList(book1, book2, book3));
Pageable pageable = PageRequest.of(0, 2, Sort.by("title").descending());
- List books = bookPagingAndSortingRepository.findBooksByAuthor("John Doe", pageable);
+ List books = bookPagingAndSortingRepository.findBooksByAuthor("John Miller", pageable);
Assertions.assertEquals(2, books.size());
Assertions.assertEquals(book3.getId(), books.get(0).getId());
Assertions.assertEquals(book2.getId(), books.get(1).getId());
diff --git a/pom.xml b/pom.xml
index 2bd9aaa0d5..327d83017f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -692,6 +692,7 @@
+ parent-boot-3
lombok-modules
osgi
spring-katharsis
@@ -726,6 +727,7 @@
spring-cloud-modules/spring-cloud-data-flow
spring-cloud-modules/spring-cloud-eureka
spring-cloud-modules/spring-cloud-netflix-feign
+ spring-cloud-modules/spring-cloud-security
spring-cloud-modules/spring-cloud-stream-starters
spring-cloud-modules/spring-cloud-zuul-eureka-integration
@@ -767,11 +769,6 @@
core-groovy-modules
core-java-modules
-
-
-
-
-
custom-pmd
data-structures
ddd-contexts
@@ -936,7 +933,8 @@
language-interop
gradle-modules/gradle/maven-to-gradle
persistence-modules/spring-data-neo4j
- parent-boot-3
+ gcp-firebase
+ spring-di-4
spring-kafka-2
@@ -972,6 +970,7 @@
+ parent-boot-3
lombok-modules
osgi
spring-katharsis
@@ -1007,6 +1006,7 @@
spring-cloud-modules/spring-cloud-data-flow
spring-cloud-modules/spring-cloud-netflix-feign
spring-cloud-modules/spring-cloud-stream-starters
+ spring-cloud-modules/spring-cloud-security
spring-cloud-modules/spring-cloud-zuul-eureka-integration
spring-exceptions
@@ -1046,7 +1046,10 @@
core-java-modules
gcp-firebase
+
+
+
@@ -1218,7 +1221,8 @@
gradle-modules/gradle/maven-to-gradle
persistence-modules/spring-data-neo4j
spring-actuator
- spring-cloud-modules/spring-cloud-contract
+ gcp-firebase
+ spring-di-4
spring-kafka-2
@@ -1236,7 +1240,6 @@
parent-boot-1
parent-boot-2
- parent-boot-3
parent-spring-4
parent-spring-5
parent-spring-6
diff --git a/spring-4/src/test/resources/logback-test.xml b/spring-4/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..a273ab5d26
--- /dev/null
+++ b/spring-4/src/test/resources/logback-test.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-5-webflux-2/README.md b/spring-5-webflux-2/README.md
index e64c88c61d..1b01f519a4 100644
--- a/spring-5-webflux-2/README.md
+++ b/spring-5-webflux-2/README.md
@@ -6,3 +6,4 @@ This module contains articles about Spring 5 WebFlux
- [Spring Webflux and @Cacheable Annotation](https://www.baeldung.com/spring-webflux-cacheable)
- [Comparison Between Mono’s doOnNext() and doOnSuccess()](https://www.baeldung.com/mono-doonnext-doonsuccess)
- [How to Access the First Element of a Flux](https://www.baeldung.com/java-flux-first-element)
+- [Using zipWhen() with Mono](https://www.baeldung.com/java-mono-zipwhen)
diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml
index 389dbf2d55..259a40dc38 100644
--- a/spring-boot-modules/pom.xml
+++ b/spring-boot-modules/pom.xml
@@ -92,6 +92,7 @@
spring-boot-3-observation
spring-boot-3-test-pitfalls
spring-boot-3-testcontainers
+ spring-boot-3-2
spring-boot-resilience4j
spring-boot-properties
spring-boot-properties-2
diff --git a/spring-boot-modules/spring-boot-3-2/pom.xml b/spring-boot-modules/spring-boot-3-2/pom.xml
new file mode 100644
index 0000000000..9e73d8ea32
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/pom.xml
@@ -0,0 +1,262 @@
+
+
+ 4.0.0
+ spring-boot-3-2
+ 0.0.1-SNAPSHOT
+ spring-boot-3-2
+ Demo project for Spring Boot
+
+
+ com.baeldung
+ parent-boot-3
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-3
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.mock-server
+ mockserver-netty
+ ${mockserver.version}
+
+
+
+ org.mock-server
+ mockserver-client-java
+ ${mockserver.version}
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc.version}
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.mapstruct
+ mapstruct
+ ${mapstruct.version}
+ true
+
+
+ org.springframework.boot
+ spring-boot-docker-compose
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+ org.springframework.amqp
+ spring-rabbit-test
+ test
+
+
+ org.springframework.data
+ spring-data-redis
+
+
+ redis.clients
+ jedis
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.postgresql
+ r2dbc-postgresql
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-data-r2dbc
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-data-elasticsearch
+
+
+ org.springframework.boot
+ spring-boot-starter-data-cassandra
+
+
+ org.springframework.boot
+ spring-boot-starter-data-neo4j
+
+
+ org.springframework.kafka
+ spring-kafka
+
+
+ org.springframework.kafka
+ spring-kafka-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-data-couchbase
+
+
+ io.micrometer
+ micrometer-tracing-bridge-brave
+
+
+ io.zipkin.reporter2
+ zipkin-reporter-brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-urlconnection
+
+
+
+
+
+
+ docker-compose
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.baeldung.dockercompose.DockerComposeApplication
+
+
+
+
+
+
+ connection-details
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.baeldung.connectiondetails.ConnectionDetailsApplication
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+ ${lombok-mapstruct-binding.version}
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ --enable-preview
+
+
+
+
+
+
+ 1.5.2.Final
+ 2.0.0
+ 3.0.0-M7
+ 5.14.0
+ 0.2.0
+
+
+
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/ConnectionDetailsApplication.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/ConnectionDetailsApplication.java
new file mode 100644
index 0000000000..d32ae8c4fb
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/ConnectionDetailsApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.connectiondetails;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+//@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+public class ConnectionDetailsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConnectionDetailsApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/adapter/VaultAdapter.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/adapter/VaultAdapter.java
new file mode 100644
index 0000000000..e8319c7735
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/adapter/VaultAdapter.java
@@ -0,0 +1,124 @@
+package com.baeldung.connectiondetails.adapter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VaultAdapter {
+ private static final Logger logger = LoggerFactory.getLogger(VaultAdapter.class);
+ public static String getSecret(String secretKey) {
+ logger.info("call vault to get the secret of key: " + secretKey);
+
+ //Postgres keys
+ if (secretKey.equalsIgnoreCase("postgres_secret_key")) {
+ return "postgres";
+ }
+ if (secretKey.equalsIgnoreCase("postgres_user_key")) {
+ return "postgres";
+ }
+ if (secretKey.equalsIgnoreCase("postgres_jdbc_url")) {
+ return "jdbc:postgresql://localhost:15432/postgresdb";
+ }
+ //RabbitMQ Server Keys
+ if (secretKey.equalsIgnoreCase("rabbitmq_username")) {
+ return "rabbitmquser";
+ }
+ if (secretKey.equalsIgnoreCase("rabbitmq_password")) {
+ return "rabbitmq";
+ }
+ if (secretKey.equalsIgnoreCase("rabbitmq_port")) {
+ return "5672";
+ }
+ if (secretKey.equalsIgnoreCase("rabbitmq_host")) {
+ return "localhost";
+ }
+ //Redis Server Keys
+ if (secretKey.equalsIgnoreCase("redis_username")) {
+ return null;
+ }
+ if (secretKey.equalsIgnoreCase("redis_password")) {
+ return "redis";
+ }
+ if (secretKey.equalsIgnoreCase("redis_port")) {
+ return "6379";
+ }
+ if (secretKey.equalsIgnoreCase("redis_host")) {
+ return "localhost";
+ }
+ //Mongo DB Keys
+ if (secretKey.equalsIgnoreCase("mongo_connection_string")) {
+ return "mongodb://localhost:27017/demodb";
+ }
+
+ //r2dbc Keys
+ if (secretKey.equalsIgnoreCase("r2dbc_postgres_user")) {
+ return "postgres";
+ }
+ if (secretKey.equalsIgnoreCase("r2dbc_postgres_secret")) {
+ return "postgres";
+ }
+ if (secretKey.equalsIgnoreCase("r2dbc_postgres_host")) {
+ return "localhost";
+ }
+ if (secretKey.equalsIgnoreCase("r2dbc_postgres_port")) {
+ return "15432";
+ }
+ if (secretKey.equalsIgnoreCase("r2dbc_postgres_database")) {
+ return "postgresdb";
+ }
+ //Elastic Search Keys
+ if (secretKey.equalsIgnoreCase("elastic_user")) {
+ return "elastic";
+ }
+ if (secretKey.equalsIgnoreCase("elastic_secret")) {
+ return "secret";
+ }
+ if (secretKey.equalsIgnoreCase("elastic_host")) {
+ return "localhost";
+ }
+ if (secretKey.equalsIgnoreCase("elastic_port1")) {
+ return "19200";
+ }
+ if (secretKey.equalsIgnoreCase("elastic_port2")) {
+ return "19300";
+ }
+ //Cassandra keys
+ if (secretKey.equalsIgnoreCase("cassandra_user")) {
+ return "cassandra";
+ }
+ if (secretKey.equalsIgnoreCase("cassandra_secret")) {
+ return "secret";
+ }
+ if (secretKey.equalsIgnoreCase("cassandra_host")) {
+ return "localhost";
+ }
+ if (secretKey.equalsIgnoreCase("cassandra_port")) {
+ return "19042";
+ }
+ //Neo4j Keys
+ if (secretKey.equalsIgnoreCase("neo4j_secret")) {
+ return "neo4j123";
+ }
+ if (secretKey.equalsIgnoreCase("neo4j_uri")) {
+ return "bolt://localhost:17687";
+ }
+ //Kafka Keys
+ if (secretKey.equalsIgnoreCase("kafka_servers")) {
+ return "localhost:19092";
+ }
+ //Couchbase Keys
+ if(secretKey.equalsIgnoreCase("couch_user")) {
+ return "Administrator";
+ }
+ if(secretKey.equalsIgnoreCase("couch_secret")) {
+ return "password";
+ }
+ if(secretKey.equalsIgnoreCase("couch_connection_string")) {
+ return "couchbase://127.0.0.1:8092";
+ }
+ //Zipkin Keys
+ if(secretKey.equalsIgnoreCase("zipkin_span_endpoint")) {
+ return "http://localhost:9411/api/v2/spans";
+ }
+ return "secretVal";
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetails.java
new file mode 100644
index 0000000000..6a246cd9fc
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetails.java
@@ -0,0 +1,32 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails;
+
+import java.util.List;
+
+public class CustomCassandraConnectionDetails implements CassandraConnectionDetails {
+ @Override
+ public List getContactPoints() {
+ Node node = new Node(
+ VaultAdapter.getSecret("cassandra_host"),
+ Integer.parseInt(VaultAdapter.getSecret("cassandra_port"))
+ );
+ return List.of(node);
+ }
+
+ @Override
+ public String getUsername() {
+ return VaultAdapter.getSecret("cassandra_user");
+ }
+
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("cassandra_secret");
+ }
+
+ @Override
+ public String getLocalDatacenter() {
+ return "datacenter-1";
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..02ed8c0051
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCassandraConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("cassandra")
+public class CustomCassandraConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public CassandraConnectionDetails getCustomCassandraConnectionDetails() {
+ return new CustomCassandraConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetails.java
new file mode 100644
index 0000000000..4fa0605cac
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetails.java
@@ -0,0 +1,21 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.couchbase.CouchbaseConnectionDetails;
+
+public class CustomCouchBaseConnectionDetails implements CouchbaseConnectionDetails {
+ @Override
+ public String getConnectionString() {
+ return VaultAdapter.getSecret("couch_connection_string");
+ }
+
+ @Override
+ public String getUsername() {
+ return VaultAdapter.getSecret("couch_user");
+ }
+
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("couch_secret");
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..96cc34f92e
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomCouchBaseConnectionDetailsConfiguration.java
@@ -0,0 +1,16 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.couchbase.CouchbaseConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("couch")
+
+public class CustomCouchBaseConnectionDetailsConfiguration {
+ @Bean
+ public CouchbaseConnectionDetails getCouchBaseConnectionDetails() {
+ return new CustomCouchBaseConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetails.java
new file mode 100644
index 0000000000..0b45878bc9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetails.java
@@ -0,0 +1,29 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
+
+import java.util.List;
+
+public class CustomElasticsearchConnectionDetails implements ElasticsearchConnectionDetails {
+ @Override
+ public List getNodes() {
+ Node node1 = new Node(
+ VaultAdapter.getSecret("elastic_host"),
+ Integer.parseInt(VaultAdapter.getSecret("elastic_port1")),
+ Node.Protocol.HTTP
+ );
+ return List.of(node1);
+ }
+
+ @Override
+ public String getUsername() {
+ return VaultAdapter.getSecret("elastic_user");
+ }
+
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("elastic_secret");
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..a9b3da44fa
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomElasticsearchConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("elastic")
+public class CustomElasticsearchConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public ElasticsearchConnectionDetails getCustomElasticConnectionDetails() {
+ return new CustomElasticsearchConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetails.java
new file mode 100644
index 0000000000..6791ee6408
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetails.java
@@ -0,0 +1,13 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.kafka.KafkaConnectionDetails;
+
+import java.util.List;
+
+public class CustomKafkaConnectionDetails implements KafkaConnectionDetails {
+ @Override
+ public List getBootstrapServers() {
+ return List.of(VaultAdapter.getSecret("kafka_servers"));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..068281741a
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomKafkaConnectionDetailsConfiguration.java
@@ -0,0 +1,15 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.kafka.KafkaConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("kafka")
+public class CustomKafkaConnectionDetailsConfiguration {
+ @Bean
+ public KafkaConnectionDetails getKafkaConnectionDetails() {
+ return new CustomKafkaConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetails.java
new file mode 100644
index 0000000000..c0412fbb21
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetails.java
@@ -0,0 +1,24 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.neo4j.driver.AuthToken;
+import org.neo4j.driver.AuthTokens;
+import org.springframework.boot.autoconfigure.neo4j.Neo4jConnectionDetails;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class CustomNeo4jConnectionDetails implements Neo4jConnectionDetails {
+ @Override
+ public URI getUri() {
+ try {
+ return new URI(VaultAdapter.getSecret("neo4j_uri"));
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ @Override
+ public AuthToken getAuthToken() {
+ return AuthTokens.basic("neo4j", VaultAdapter.getSecret("neo4j_secret"));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..aec8908c7d
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomNeo4jConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.neo4j.Neo4jConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("neo4j")
+public class CustomNeo4jConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public Neo4jConnectionDetails getNeo4jConnectionDetails() {
+ return new CustomNeo4jConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetails.java
new file mode 100644
index 0000000000..c29408992a
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetails.java
@@ -0,0 +1,11 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConnectionDetails;
+
+public class CustomZipkinConnectionDetails implements ZipkinConnectionDetails {
+ @Override
+ public String getSpanEndpoint() {
+ return VaultAdapter.getSecret("zipkin_span_endpoint");
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..2f451a3850
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/CustomZipkinConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("zipkin")
+public class CustomZipkinConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public ZipkinConnectionDetails getZipkinConnectionDetails() {
+ return new CustomZipkinConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/JdbcConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/JdbcConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..3387356366
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/JdbcConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("jdbc")
+public class JdbcConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public JdbcConnectionDetails getPostgresConnection() {
+ return new PostgresConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetails.java
new file mode 100644
index 0000000000..df689d81b6
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetails.java
@@ -0,0 +1,14 @@
+package com.baeldung.connectiondetails.configuration;
+
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import com.mongodb.ConnectionString;
+import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
+
+public class MongoDBConnectionDetails implements MongoConnectionDetails {
+ @Override
+ public ConnectionString getConnectionString() {
+ return new ConnectionString(VaultAdapter.getSecret("mongo_connection_string"));
+ }
+}
+
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..d455991d08
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/MongoDBConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("mongo")
+public class MongoDBConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public MongoConnectionDetails getMongoConnectionDetails() {
+ return new MongoDBConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/PostgresConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/PostgresConnectionDetails.java
new file mode 100644
index 0000000000..c9b213a8d3
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/PostgresConnectionDetails.java
@@ -0,0 +1,21 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
+
+public class PostgresConnectionDetails implements JdbcConnectionDetails {
+ @Override
+ public String getUsername() {
+ return VaultAdapter.getSecret("postgres_user_key");
+ }
+
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("postgres_secret_key");
+ }
+
+ @Override
+ public String getJdbcUrl() {
+ return VaultAdapter.getSecret("postgres_jdbc_url");
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetails.java
new file mode 100644
index 0000000000..613ec83124
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetails.java
@@ -0,0 +1,22 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import io.r2dbc.spi.ConnectionFactoryOptions;
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails;
+
+public class R2dbcPostgresConnectionDetails implements R2dbcConnectionDetails {
+ @Override
+ public ConnectionFactoryOptions getConnectionFactoryOptions() {
+
+ ConnectionFactoryOptions options = ConnectionFactoryOptions.builder()
+ .option(ConnectionFactoryOptions.DRIVER, "postgresql")
+ .option(ConnectionFactoryOptions.HOST, VaultAdapter.getSecret("r2dbc_postgres_host"))
+ .option(ConnectionFactoryOptions.PORT, Integer.valueOf(VaultAdapter.getSecret("r2dbc_postgres_port")))
+ .option(ConnectionFactoryOptions.USER, VaultAdapter.getSecret("r2dbc_postgres_user"))
+ .option(ConnectionFactoryOptions.PASSWORD, VaultAdapter.getSecret("r2dbc_postgres_secret"))
+ .option(ConnectionFactoryOptions.DATABASE, VaultAdapter.getSecret("r2dbc_postgres_database"))
+ .build();
+
+ return options;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..144355dce4
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/R2dbcPostgresConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("r2dbc")
+public class R2dbcPostgresConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public R2dbcConnectionDetails getR2dbcPostgresConnectionDetails() {
+ return new R2dbcPostgresConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetails.java
new file mode 100644
index 0000000000..9dc4bdf33b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetails.java
@@ -0,0 +1,34 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;
+
+import java.util.List;
+
+public class RabbitMQConnectionDetails implements RabbitConnectionDetails {
+ @Override
+ public String getUsername() {
+ return VaultAdapter.getSecret("rabbitmq_username");
+ }
+
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("rabbitmq_password");
+ }
+
+ @Override
+ public String getVirtualHost() {
+ return "/";
+ }
+
+ @Override
+ public List getAddresses() {
+ return List.of(this.getFirstAddress());
+ }
+
+ @Override
+ public Address getFirstAddress() {
+ return new Address(VaultAdapter.getSecret("rabbitmq_host"),
+ Integer.parseInt(VaultAdapter.getSecret("rabbitmq_port")));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..237bec3fc4
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RabbitMQConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("rabbitmq")
+public class RabbitMQConnectionDetailsConfiguration {
+ @Primary
+ @Bean
+ public RabbitConnectionDetails getRabbitmqConnection() {
+ return new RabbitMQConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisCacheConnectionDetails.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisCacheConnectionDetails.java
new file mode 100644
index 0000000000..9485f22240
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisCacheConnectionDetails.java
@@ -0,0 +1,26 @@
+package com.baeldung.connectiondetails.configuration;
+
+import com.baeldung.connectiondetails.adapter.VaultAdapter;
+import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails;
+
+public class RedisCacheConnectionDetails implements RedisConnectionDetails {
+ @Override
+ public String getPassword() {
+ return VaultAdapter.getSecret("redis_password");
+ }
+
+ @Override
+ public Standalone getStandalone() {
+ return new Standalone() {
+ @Override
+ public String getHost() {
+ return VaultAdapter.getSecret("redis_host");
+ }
+
+ @Override
+ public int getPort() {
+ return Integer.parseInt(VaultAdapter.getSecret("redis_port"));
+ }
+ };
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisConnectionDetailsConfiguration.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisConnectionDetailsConfiguration.java
new file mode 100644
index 0000000000..31816ff0b4
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/configuration/RedisConnectionDetailsConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.connectiondetails.configuration;
+
+import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+@Configuration(proxyBeanMethods = false)
+@Profile("redis")
+public class RedisConnectionDetailsConfiguration {
+ @Bean
+ @Primary
+ public RedisConnectionDetails getRedisCacheConnection() {
+ return new RedisCacheConnectionDetails();
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/controller/ZipkinDemoController.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/controller/ZipkinDemoController.java
new file mode 100644
index 0000000000..bba5607ccd
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/controller/ZipkinDemoController.java
@@ -0,0 +1,19 @@
+package com.baeldung.connectiondetails.controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ZipkinDemoController {
+
+ Logger logger = LoggerFactory.getLogger(ZipkinDemoController.class);
+
+ @GetMapping("/zipkin/test")
+ public @ResponseBody String testMethod() {
+ logger.info("This is a test");
+ return "This is a test";
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/elastic/Person.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/elastic/Person.java
new file mode 100644
index 0000000000..851dbb7c90
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/elastic/Person.java
@@ -0,0 +1,27 @@
+package com.baeldung.connectiondetails.entity.elastic;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.elasticsearch.annotations.Document;
+
+@Document(indexName = "person")
+public class Person {
+ String name;
+ @Id
+ String ssn;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSsn() {
+ return ssn;
+ }
+
+ public void setSsn(String ssn) {
+ this.ssn = ssn;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/neo4j/Person.java b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/neo4j/Person.java
new file mode 100644
index 0000000000..63e88d0a41
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/java/com/baeldung/connectiondetails/entity/neo4j/Person.java
@@ -0,0 +1,27 @@
+package com.baeldung.connectiondetails.entity.neo4j;
+
+import org.springframework.data.neo4j.core.schema.Id;
+import org.springframework.data.neo4j.core.schema.Node;
+
+@Node
+public class Person {
+ @Id
+ String name;
+ String zipcode;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getZipcode() {
+ return zipcode;
+ }
+
+ public void setZipcode(String zipcode) {
+ this.zipcode = zipcode;
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-cassandra.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-cassandra.properties
new file mode 100644
index 0000000000..4098206d21
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-cassandra.properties
@@ -0,0 +1,11 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-cassandra.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=cassandra
+spring.cassandra.local-datacenter=dc1
+#spring.cassandra.keyspace-name=spring_cassandra
+#spring.cassandra.schema-action=CREATE_IF_NOT_EXISTS
+spring.data.cassandra.request.timeout=20000 # Set your desired timeout in milliseconds
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-couch.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-couch.properties
new file mode 100644
index 0000000000..ccce04c0b5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-couch.properties
@@ -0,0 +1,8 @@
+spring.profiles.active=couch
+spring.docker.compose.enabled=false
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-couch.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.couchbase.bucket.name=travel-sample
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClientAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-elastic.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-elastic.properties
new file mode 100644
index 0000000000..2149730517
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-elastic.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-elastic.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=elastic
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-jdbc.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-jdbc.properties
new file mode 100644
index 0000000000..b5a8a73bcf
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-jdbc.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-jdbc.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=jdbc
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-kafka.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-kafka.properties
new file mode 100644
index 0000000000..9f756cfaf1
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-kafka.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-kafka.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=kafka
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-mongo.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-mongo.properties
new file mode 100644
index 0000000000..31d828c5c9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-mongo.properties
@@ -0,0 +1,8 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-mongo.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=mongo
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
+spring.data.mongodb.database=demodb
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-neo4j.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-neo4j.properties
new file mode 100644
index 0000000000..e2dc9e20bf
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-neo4j.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-neo4j.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=neo4j
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-r2dbc.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-r2dbc.properties
new file mode 100644
index 0000000000..3fcaa4f746
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-r2dbc.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-jdbc.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=r2dbc
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-rabbitmq.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-rabbitmq.properties
new file mode 100644
index 0000000000..fa6b3f6608
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-rabbitmq.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-rabbitmq.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=rabbitmq
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-redis.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-redis.properties
new file mode 100644
index 0000000000..c12f20c773
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-redis.properties
@@ -0,0 +1,7 @@
+spring.docker.compose.enabled=true
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-redis.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.profiles.active=redis
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-zipkin.properties b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-zipkin.properties
new file mode 100644
index 0000000000..544a3c07b6
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/application-zipkin.properties
@@ -0,0 +1,9 @@
+spring.profiles.active=zipkin
+spring.docker.compose.enabled=false
+spring.docker.compose.file=./connectiondetails/docker/docker-compose-zipkin.yml
+spring.docker.compose.skip.in-tests=false
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+spring.mustache.check-template-location=false
+spring.application.name=baeldung
+management.tracing.sampling.probability=1.0
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClientAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-cassandra.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-cassandra.yml
new file mode 100644
index 0000000000..c593cbc73b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-cassandra.yml
@@ -0,0 +1,9 @@
+version: '3.8'
+services:
+ cassandra:
+ image: 'cassandra:latest'
+ environment:
+ - 'CASSANDRA_DC=datacenter-1'
+ - 'CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch'
+ ports:
+ - '19042:9042'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-couch.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-couch.yml
new file mode 100644
index 0000000000..edcf8e2e08
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-couch.yml
@@ -0,0 +1,12 @@
+version: '3.8'
+services:
+ couchbase:
+ image: couchbase/server-sandbox:7.0.0
+ ports:
+ - "8091-8095:8091-8095"
+ - "9102:9102"
+ - "11210:11210"
+ expose:
+ - "8091"
+ - "8094"
+ container_name: couchbase-sandbox-7.0.0-mm
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-elastic.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-elastic.yml
new file mode 100644
index 0000000000..a6e51ee1a0
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-elastic.yml
@@ -0,0 +1,12 @@
+version: '3.8'
+services:
+ elasticsearch:
+ image: 'docker.elastic.co/elasticsearch/elasticsearch:7.17.10'
+ environment:
+ - 'ELASTIC_USERNAME=elastic'
+ - 'ELASTIC_PASSWORD=secret'
+ - 'discovery.type=single-node'
+ - 'xpack.security.enabled=false'
+ ports:
+ - '19200:9200'
+# - '19300:9300'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-jdbc.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-jdbc.yml
new file mode 100644
index 0000000000..65a8f135e8
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-jdbc.yml
@@ -0,0 +1,10 @@
+version: '3.8'
+services:
+ database:
+ image: 'postgres:13.1-alpine'
+ ports:
+ - '15432:5432'
+ environment:
+ - 'POSTGRES_USER=postgres'
+ - 'POSTGRES_DB=postgresdb'
+ - 'POSTGRES_PASSWORD=postgres'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-kafka.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-kafka.yml
new file mode 100644
index 0000000000..5d13e6d6cc
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-kafka.yml
@@ -0,0 +1,38 @@
+version: '3'
+services:
+ zookeeper:
+ image: confluentinc/cp-zookeeper:latest
+ container_name: zookeeper
+ environment:
+ ZOOKEEPER_CLIENT_PORT: 2181
+ ZOOKEEPER_TICK_TIME: 2000
+ ports:
+ - "2181:2181"
+
+ schema-registry:
+ image: confluentinc/cp-schema-registry:latest
+ hostname: schema-registry
+ depends_on:
+ - kafka-broker-1
+ ports:
+ - "8081:8081"
+ environment:
+ SCHEMA_REGISTRY_HOST_NAME: schema-registry
+ SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+ SCHEMA_REGISTRY_LISTENERS: http://schema-registry:8081
+ SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka-broker-1:9092,PLAINTEXT_INTERNAL://localhost:19092
+ SCHEMA_REGISTRY_DEBUG: 'true'
+
+ kafka-broker-1:
+ image: confluentinc/cp-kafka:latest
+ hostname: kafka-broker-1
+ ports:
+ - "19092:19092"
+ depends_on:
+ - zookeeper
+ environment:
+ KAFKA_BROKER_ID: 1
+ KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-broker-1:9092,PLAINTEXT_INTERNAL://localhost:19092
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-mongo.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-mongo.yml
new file mode 100644
index 0000000000..f12f5c3aa7
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-mongo.yml
@@ -0,0 +1,10 @@
+version: '3.8'
+services:
+ mongodb:
+ image: 'mongo:latest'
+ environment:
+ - 'MONGO_INITDB_DATABASE=demodb'
+# - 'MONGO_INITDB_ROOT_PASSWORD=Mongo123'
+# - 'MONGO_INITDB_ROOT_USERNAME=mongouser'
+ ports:
+ - '27017:27017'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-neo4j.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-neo4j.yml
new file mode 100644
index 0000000000..611951e755
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-neo4j.yml
@@ -0,0 +1,8 @@
+version: '3.8'
+services:
+ neo4j:
+ image: 'neo4j:latest'
+ ports:
+ - '17687:7687'
+ environment:
+ NEO4J_AUTH: neo4j/neo4j123
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-rabbitmq.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-rabbitmq.yml
new file mode 100644
index 0000000000..8abf19bd19
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-rabbitmq.yml
@@ -0,0 +1,9 @@
+version: '3.8'
+services:
+ rabbitmq:
+ image: 'rabbitmq:latest'
+ environment:
+ - 'RABBITMQ_DEFAULT_PASS=rabbitmq'
+ - 'RABBITMQ_DEFAULT_USER=rabbitmquser'
+ ports:
+ - '5672:5672'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-redis.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-redis.yml
new file mode 100644
index 0000000000..c218cef998
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-redis.yml
@@ -0,0 +1,8 @@
+version: '3.8'
+services:
+ redis:
+ image: 'redis:latest'
+ ports:
+ - '6379:6379'
+ environment:
+ - 'REDIS_REQUIREPASS=redis'
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-zipkin.yml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-zipkin.yml
new file mode 100644
index 0000000000..363dd24a2b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/docker/docker-compose-zipkin.yml
@@ -0,0 +1,10 @@
+version: '3'
+services:
+ zipkin:
+ image: 'openzipkin/zipkin:latest'
+ ports:
+ - "9411:9411"
+# environment:
+# - ZIPKIN_AUTH_USERNAME=your-username
+# - ZIPKIN_AUTH_PASSWORD=your-password
+ # Add other necessary configurations here
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/cassandra-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/cassandra-connection-details-class-diag.puml
new file mode 100644
index 0000000000..b16ef4d56e
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/cassandra-connection-details-class-diag.puml
@@ -0,0 +1,27 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface CassandraConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getContactPoints():List
+ +getLocalDatacenter():String
+}
+class CustomCouchBaseConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getContactPoints():List
+ +getLocalDatacenter():String
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomCassandraConnectionDetailsConfiguration {
+ +getCustomCassandraConnectionDetails():CassandraConnectionDetails
+}
+CustomCouchBaseConnectionDetails -left-> VaultAdapter:uses
+CustomCouchBaseConnectionDetails -right-|> CassandraConnectionDetails : implements
+CustomCassandraConnectionDetailsConfiguration -up-> CustomCassandraConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/connection-details-sequence-design.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/connection-details-sequence-design.puml
new file mode 100644
index 0000000000..a2a917eea0
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/connection-details-sequence-design.puml
@@ -0,0 +1,16 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+skinparam sequenceMessageAlign direction
+skinparam handwritten true
+skinparam sequence {
+ParticipantBackgroundColor beige
+ParticipantPadding 50
+}
+autonumber
+
+"Spring Boot" -[#63b175]> "Hashicorp Vault": Secret Request
+"Hashicorp Vault" -[#63b175]-> "Spring Boot": Secret Response
+"Spring Boot" -[#63b175]> "Remote Service": Connection Request
+
+"Remote Service" -[#63b175]-> "Spring Boot": Connection Response
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/couch_connection_details_class_diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/couch_connection_details_class_diag.puml
new file mode 100644
index 0000000000..fd8dbd094b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/couch_connection_details_class_diag.puml
@@ -0,0 +1,25 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface CouchbaseConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getConnectionString():String
+}
+class CustomCouchBaseConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getConnectionString():String
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomCouchBaseConnectionDetailsConfiguration {
+ +getCouchBaseConnectionDetails():CouchbaseConnectionDetails
+}
+CustomCouchBaseConnectionDetails -left-> VaultAdapter:uses
+CustomCouchBaseConnectionDetails -right-|> CouchbaseConnectionDetails : implements
+CustomCouchBaseConnectionDetailsConfiguration -up-> CustomCouchBaseConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/elasticsearch-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/elasticsearch-connection-details-class-diag.puml
new file mode 100644
index 0000000000..48db0bcc4f
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/elasticsearch-connection-details-class-diag.puml
@@ -0,0 +1,25 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface ElasticsearchConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getNodes():List
+}
+class CustomElasticsearchConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getNodes():List
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomElasticsearchConnectionDetailsConfiguration {
+ +getCustomElasticConnectionDetails():ElasticsearchConnectionDetails
+}
+CustomElasticsearchConnectionDetails -left-> VaultAdapter:uses
+CustomElasticsearchConnectionDetails -right-|> ElasticsearchConnectionDetails : implements
+CustomElasticsearchConnectionDetailsConfiguration -up-> CustomElasticsearchConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/jdbcconnection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/jdbcconnection-details-class-diag.puml
new file mode 100644
index 0000000000..88de5d607f
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/jdbcconnection-details-class-diag.puml
@@ -0,0 +1,25 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface JdbcConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getJdbcUrl():String
+}
+class PostgresConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getJdbcUrl():String
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class JdbcConnectonDetailsConfiguration {
+ +getPostgresConnection():JdbcConnectionDetails
+}
+PostgresConnectionDetails -left-> VaultAdapter:uses
+PostgresConnectionDetails -right-|> JdbcConnectionDetails : implements
+JdbcConnectonDetailsConfiguration -up-> PostgresConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/kafka-connectiondetails-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/kafka-connectiondetails-class-diag.puml
new file mode 100644
index 0000000000..57df331bb2
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/kafka-connectiondetails-class-diag.puml
@@ -0,0 +1,21 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface KafkaConnectionDetails {
+ +getBootstrapServers():List
+}
+class CustomKafkaConnectionDetails {
++getBootstrapServers():List
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomKafkaConnectionDetailsConfiguration {
+ +getKafkaConnectionDetails():KafkaConnectionDetails
+}
+CustomKafkaConnectionDetails -left-> VaultAdapter:uses
+CustomKafkaConnectionDetails -right-|> KafkaConnectionDetails:implements
+CustomKafkaConnectionDetailsConfiguration -up-> CustomKafkaConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/mongodb-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/mongodb-connection-details-class-diag.puml
new file mode 100644
index 0000000000..974c6de601
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/mongodb-connection-details-class-diag.puml
@@ -0,0 +1,19 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface MongoConnectionDetails {
+ getConnectionString():ConnectionString
+}
+class MongoDBConnectionDetails {
+ getConnectionString():ConnectionString
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class MongoDBConnectionDetailsConfiguration {
+ +getMongoConnectionDetails() : MongoConnectionDetails
+}
+MongoDBConnectionDetails -left-> VaultAdapter:uses
+MongoDBConnectionDetails -right-|> MongoConnectionDetails : implements
+MongoDBConnectionDetailsConfiguration -up-> MongoDBConnectionDetails:uses
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/neo4j-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/neo4j-connection-details-class-diag.puml
new file mode 100644
index 0000000000..5a3e8812f6
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/neo4j-connection-details-class-diag.puml
@@ -0,0 +1,23 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface Neo4jConnectionDetails {
+ +getUri():URI
+ +getAuthToken():AuthToken
+}
+class CustomNeo4jConnectionDetails {
+ +getUri():URI
+ +getAuthToken():AuthToken
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomNeo4jConnectionDetailsConfiguration {
+ +getNeo4jConnectionDetails():Neo4jConnectionDetails
+}
+CustomNeo4jConnectionDetails -left-> VaultAdapter:uses
+CustomNeo4jConnectionDetails -right-|> Neo4jConnectionDetails:implements
+CustomNeo4jConnectionDetailsConfiguration -up-> CustomNeo4jConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/r2dbcconnection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/r2dbcconnection-details-class-diag.puml
new file mode 100644
index 0000000000..ec69587ab9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/r2dbcconnection-details-class-diag.puml
@@ -0,0 +1,21 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface R2dbcConnectionDetails {
+ +getConnectionFactoryOptions():ConnectionFactoryOptions
+}
+class R2dbcPostgresConnectionDetails {
+ +getConnectionFactoryOptions():ConnectionFactoryOptions
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class R2dbcPostgresConnectionDetailsConfiguration {
+ +getR2dbcPostgresConnectionDetails():R2dbcConnectionDetails
+}
+R2dbcPostgresConnectionDetails -right-> VaultAdapter:uses
+R2dbcPostgresConnectionDetails -up-|> R2dbcConnectionDetails:implements
+R2dbcPostgresConnectionDetailsConfiguration -up-> R2dbcPostgresConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/rabbitmq-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/rabbitmq-connection-details-class-diag.puml
new file mode 100644
index 0000000000..0541e12915
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/rabbitmq-connection-details-class-diag.puml
@@ -0,0 +1,27 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface RabbitConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getFirstAddress():Address
+ +getAddresses():List
+}
+class RabbitMQConnectionDetails {
+ +getUsername():String
+ +getPassword():String
+ +getFirstAddress():Address
+ +getAddresses():List
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class RabbitMQConnectionDetailsConfiguration {
+ +getRabbitmqConnection() : RabbitConnectionDetails
+}
+RabbitMQConnectionDetails -left-> VaultAdapter:uses
+RabbitMQConnectionDetails -right-|> RabbitConnectionDetails : implements
+RabbitMQConnectionDetailsConfiguration -up-> RabbitMQConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/redis-connection-details-class-diagram.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/redis-connection-details-class-diagram.puml
new file mode 100644
index 0000000000..a18c83a8be
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/redis-connection-details-class-diagram.puml
@@ -0,0 +1,23 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface RedisConnectionDetails {
+ +getPassword():String
+ +getStandalone():Standalone
+}
+class RedisCacheConnectionDetails {
+ +getPassword():String
+ +getStandalone():Standalone
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class RedisConnectonDetailsConfiguration {
+ +getRedisCacheConnection():RedisConnectionDetails
+}
+RedisCacheConnectionDetails -left-> VaultAdapter:uses
+RedisCacheConnectionDetails -right-|> RedisConnectionDetails : implements
+RedisConnectonDetailsConfiguration -up-> RedisCacheConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/zipkin-connection-details-class-diag.puml b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/zipkin-connection-details-class-diag.puml
new file mode 100644
index 0000000000..0f185f9c12
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/main/resources/connectiondetails/plantuml/zipkin-connection-details-class-diag.puml
@@ -0,0 +1,21 @@
+@startuml
+'https://plantuml.com/class-diagram
+
+interface ZipkinConnectionDetails {
+ +getSpanEndpoint():String
+}
+class CustomZipkinConnectionDetails {
+ +getSpanEndpoint():String
+}
+class VaultAdapter {
+ +getSecret(String secretKey):String
+}
+class CustomZipkinConnectionDetailsConfiguration {
+ +getZipkinConnectionDetails():ZipkinConnectionDetails
+}
+CustomZipkinConnectionDetails -left-> VaultAdapter:uses
+CustomZipkinConnectionDetails -right-|> ZipkinConnectionDetails:implements
+CustomZipkinConnectionDetailsConfiguration -up-> CustomZipkinConnectionDetails:uses
+
+
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CassandraConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CassandraConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..4130b6cb6b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CassandraConnectionDetailsIntegrationTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.CustomCassandraConnectionDetailsConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.cassandra.core.CassandraTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(CustomCassandraConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-cassandra.properties"})
+@ActiveProfiles("cassandra")
+public class CassandraConnectionDetailsIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(CassandraConnectionDetailsIntegrationTest.class);
+ @Autowired
+ private CassandraTemplate cassandraTemplate;
+ @Test
+ public void givenHashicorpVault_whenRunQuery_thenSuccess() {
+ boolean result = cassandraTemplate.getCqlOperations()
+ .execute("CREATE KEYSPACE IF NOT EXISTS spring_cassandra"
+ + " WITH replication = {'class':'SimpleStrategy', 'replication_factor':3}");
+ logger.info("the result -" + result);
+ assertTrue(result);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CouchbaseConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CouchbaseConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..454aad4c6c
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/CouchbaseConnectionDetailsIntegrationTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.CustomCouchBaseConnectionDetailsConfiguration;
+import com.couchbase.client.java.Cluster;
+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.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(CustomCouchBaseConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-couch.properties"})
+@ActiveProfiles("couch")
+public class CouchbaseConnectionDetailsIntegrationTest {
+ @Autowired
+ private Cluster cluster;
+ @Test
+ public void givenSecretVault_whenConnectWithCouch_thenSuccess() {
+ assertDoesNotThrow(cluster.ping()::version);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/ElasticsearchConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/ElasticsearchConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..ee698cd6ea
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/ElasticsearchConnectionDetailsIntegrationTest.java
@@ -0,0 +1,45 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.CustomElasticsearchConnectionDetailsConfiguration;
+import com.baeldung.connectiondetails.entity.elastic.Person;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(CustomElasticsearchConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-elastic.properties"})
+@ActiveProfiles("elastic")
+public class ElasticsearchConnectionDetailsIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConnectionDetailsIntegrationTest.class);
+ @Autowired
+ private ElasticsearchTemplate elasticsearchTemplate;
+
+ @Before
+ public void prepare() {
+ if (elasticsearchTemplate.indexOps(Person.class).exists()) {
+ elasticsearchTemplate.indexOps(Person.class).delete();
+ }
+ }
+ @Test
+ public void givenHashicorpVault_whenCreateIndexInElastic_thenSuccess() {
+
+ boolean result = elasticsearchTemplate.indexOps(Person.class).create();
+ logger.info("index created:" + result);
+ assertTrue(result);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/JdbcConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/JdbcConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..748bc27b0b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/JdbcConnectionDetailsIntegrationTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.JdbcConnectionDetailsConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.sql.Date;
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(JdbcConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-jdbc.properties"})
+@ActiveProfiles("jdbc")
+public class JdbcConnectionDetailsIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(JdbcConnectionDetailsIntegrationTest.class);
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+ @Test
+ public void givenSecretVault_whenIntegrateWithPostgres_thenConnectionSuccessful() {
+ String sql = "select current_date;";
+ Date date = jdbcTemplate.queryForObject(sql, Date.class);
+ assertEquals(LocalDate.now().toString(), date.toString());
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/KafkaConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/KafkaConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..bc0e174b3f
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/KafkaConnectionDetailsIntegrationTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.CustomKafkaConnectionDetailsConfiguration;
+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.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(CustomKafkaConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-kafka.properties"})
+@ActiveProfiles("kafka")
+public class KafkaConnectionDetailsIntegrationTest {
+ @Autowired
+ private KafkaTemplate kafkaTemplate;
+
+ @Test
+ public void givenSecretVault_whenPublishMsgToKafkaQueue_thenSuccess() {
+ assertDoesNotThrow(kafkaTemplate::getDefaultTopic);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/MongoDBConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/MongoDBConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..868ebfea98
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/MongoDBConnectionDetailsIntegrationTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.MongoDBConnectionDetailsConfiguration;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration;
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(MongoDBConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-mongo.properties"})
+@ActiveProfiles("mongo")
+public class MongoDBConnectionDetailsIntegrationTest {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+ @Test
+ public void givenSecretVault_whenExecuteQueryOnMongoDB_ReturnResult() throws JSONException {
+ mongoTemplate.insert("{\"msg\":\"My First Entry in MongoDB\"}", "myDemoCollection");
+ String result = mongoTemplate.find(new Query(), String.class, "myDemoCollection").get(0);
+
+ JSONObject jsonObject = new JSONObject(result);
+ result = jsonObject.get("msg").toString();
+ R2dbcAutoConfiguration r2dbcAutoConfiguration;
+ R2dbcDataAutoConfiguration r2dbcDataAutoConfiguration;
+ R2dbcRepositoriesAutoConfiguration r2dbcRepositoriesAutoConfiguration;
+
+ assertEquals("My First Entry in MongoDB", result);
+ }
+}
+
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/Neo4jConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/Neo4jConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..943ed7bdea
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/Neo4jConnectionDetailsIntegrationTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.CustomNeo4jConnectionDetailsConfiguration;
+import com.baeldung.connectiondetails.entity.neo4j.Person;
+import org.junit.After;
+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.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.neo4j.core.Neo4jTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(CustomNeo4jConnectionDetailsConfiguration.class)
+@ComponentScan(basePackages = "com.baeldung.connectiondetails")
+@TestPropertySource(locations = {"classpath:connectiondetails/application-neo4j.properties"})
+@ActiveProfiles("neo4j")
+public class Neo4jConnectionDetailsIntegrationTest {
+ @Autowired
+ private Neo4jTemplate neo4jTemplate;
+
+ @After
+ public void cleanup() {
+ neo4jTemplate.deleteAll(Person.class);
+ }
+ @Test
+ public void giveSecretVault_whenRunQuery_thenSuccess() {
+ Person person = new Person();
+ person.setName("James");
+ person.setZipcode("751003");
+
+ Person data = neo4jTemplate.save(person);
+ assertEquals("James", data.getName());
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/R2dbcConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/R2dbcConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..5f8c8349fb
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/R2dbcConnectionDetailsIntegrationTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.R2dbcPostgresConnectionDetailsConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(R2dbcPostgresConnectionDetailsConfiguration.class)
+@TestPropertySource(locations = {"classpath:connectiondetails/application-r2dbc.properties"})
+@ActiveProfiles("r2dbc")
+public class R2dbcConnectionDetailsIntegrationTest {
+ Logger logger = LoggerFactory.getLogger(R2dbcConnectionDetailsIntegrationTest.class);
+ @Autowired
+ private R2dbcEntityTemplate r2dbcEntityTemplate;
+
+ @Test
+ public void givenSecretVault_whenQueryPostgresReactive_thenSuccess() {
+
+ String sql = "select * from information_schema.tables";
+
+ List result = r2dbcEntityTemplate.getDatabaseClient().sql(sql).fetch().all()
+ .map(r -> {
+ return "hello " + r.get("table_name").toString();
+ }).collectList().block();
+ logger.info("count ------" + result.size());
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RabbitmqConnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RabbitmqConnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..9e10973ed7
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RabbitmqConnectionDetailsIntegrationTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.RabbitMQConnectionDetailsConfiguration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(RabbitMQConnectionDetailsConfiguration.class)
+@TestPropertySource(locations = {"classpath:connectiondetails/application-rabbitmq.properties"})
+@ActiveProfiles("rabbitmq")
+public class RabbitmqConnectionDetailsIntegrationTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(RabbitmqConnectionDetailsIntegrationTest.class);
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+ @Autowired
+ private CachingConnectionFactory connectionFactory;
+
+ private final static String queueName = "Test_Queue";
+
+ RabbitAdmin rabbitAdmin;
+
+ @Before
+ public void setup() {
+ logger.info("create new queue");
+ rabbitAdmin = new RabbitAdmin(connectionFactory);
+ logger.info("creating queue: " + rabbitAdmin.declareQueue(new Queue(queueName)));
+ connectionFactory.destroy();
+ }
+
+ @After
+ public void cleanup() {
+ logger.info("delete queue");
+ this.rabbitAdmin.deleteQueue(queueName, false, true);
+ }
+ @Test
+ public void givenSecretVault_whenPublishMessageToRabbitmq_thenSuccess() {
+ logger.info("sending message to queue " + queueName);
+ final String MSG = "this is a test message";
+ this.rabbitTemplate.convertAndSend(queueName, MSG);
+ assertEquals(MSG, this.rabbitTemplate.receiveAndConvert(queueName));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RedisCacheConnnectionDetailsIntegrationTest.java b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RedisCacheConnnectionDetailsIntegrationTest.java
new file mode 100644
index 0000000000..5dbd2d6c03
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-2/src/test/java/com/baeldung/connectiondetails/RedisCacheConnnectionDetailsIntegrationTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.connectiondetails;
+
+import com.baeldung.connectiondetails.configuration.RedisConnectionDetailsConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConnectionDetailsApplication.class)
+@Import(RedisConnectionDetailsConfiguration.class)
+@TestPropertySource(locations = {"classpath:connectiondetails/application-redis.properties"})
+@ActiveProfiles("redis")
+public class RedisCacheConnnectionDetailsIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(RedisCacheConnnectionDetailsIntegrationTest.class);
+
+ @Autowired
+ RedisTemplate redisTemplate;
+
+ @Test
+ public void giveSecretVault_whenStoreInRedisCache_thenSuccess() {
+ redisTemplate.opsForValue().set("City", "New York");
+ assertEquals("New York", redisTemplate.opsForValue().get("City"));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/README.md b/spring-boot-modules/spring-boot-3-testcontainers/README.md
index 183c64faae..e6aa952295 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/README.md
+++ b/spring-boot-modules/spring-boot-3-testcontainers/README.md
@@ -1,2 +1,3 @@
## Relevant Articles
- [Built-in Testcontainers Support in Spring Boot](https://www.baeldung.com/spring-boot-built-in-testcontainers)
+- [How to Reuse Testcontainers in Java](https://www.baeldung.com/java-reuse-testcontainers)
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/reuse/ReusableContainersLiveTest.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/reuse/ReusableContainersLiveTest.java
new file mode 100644
index 0000000000..4a96160e32
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/reuse/ReusableContainersLiveTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.testcontainers.reuse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.MongoDBContainer;
+import org.testcontainers.utility.DockerImageName;
+
+import com.baeldung.testcontainers.support.MiddleEarthCharacter;
+import com.baeldung.testcontainers.support.MiddleEarthCharactersRepository;
+
+@SpringBootTest
+class ReusableContainersLiveTest {
+
+ static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))
+ .withReuse(true);
+
+ @BeforeAll
+ static void beforeAll() {
+ mongoDBContainer.start();
+ }
+
+ @DynamicPropertySource
+ static void setProperties(DynamicPropertyRegistry registry) {
+ registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
+ }
+
+ @Autowired
+ private MiddleEarthCharactersRepository repository;
+
+ @Test
+ void whenRunningMultipleTimes_thenContainerShouldBeReused_andTestShouldFail() {
+ assertThat(repository.findAll())
+ .isEmpty();
+
+ repository.saveAll(List.of(
+ new MiddleEarthCharacter("Frodo", "hobbit"),
+ new MiddleEarthCharacter("Samwise", "hobbit"))
+ );
+
+ assertThat(repository.findAll())
+ .hasSize(2);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/DynamicPropertiesLiveTest.java
similarity index 98%
rename from spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java
rename to spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/DynamicPropertiesLiveTest.java
index 2633f227d4..d2511286e3 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/DynamicPropertiesLiveTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.testcontainers;
+package com.baeldung.testcontainers.support;
import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.hasItems;
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/LocalDevApplication.java
similarity index 95%
rename from spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java
rename to spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/LocalDevApplication.java
index 1b6fe32c97..0b49fba26b 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/LocalDevApplication.java
@@ -7,6 +7,7 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnect
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.utility.DockerImageName;
+import com.baeldung.testcontainers.Application;
// Testcontainers require a valid docker installation.
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/ServiceConnectionLiveTest.java
similarity index 97%
rename from spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java
rename to spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/ServiceConnectionLiveTest.java
index 51b69c44b3..a93c136e1c 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/support/ServiceConnectionLiveTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.testcontainers;
+package com.baeldung.testcontainers.support;
import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.hasItems;
diff --git a/spring-boot-modules/spring-boot-3/src/main/resources/application-docker-compose.yml b/spring-boot-modules/spring-boot-3/src/main/resources/application-docker-compose.yml
deleted file mode 100644
index bce67fa400..0000000000
--- a/spring-boot-modules/spring-boot-3/src/main/resources/application-docker-compose.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-spring:
- docker:
- compose:
- enabled: true
- file: docker-compose.yml
- autoconfigure:
- exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-aws/pom.xml b/spring-boot-modules/spring-boot-aws/pom.xml
index 460acae247..44cd38be3f 100644
--- a/spring-boot-modules/spring-boot-aws/pom.xml
+++ b/spring-boot-modules/spring-boot-aws/pom.xml
@@ -14,6 +14,7 @@
org.springframework.boot
spring-boot-starter-parent
2.7.11
+
diff --git a/spring-boot-modules/spring-boot-swagger-springfox/src/main/java/com/baeldung/springdoc/demo/controller/SwaggerController.java b/spring-boot-modules/spring-boot-swagger-springfox/src/main/java/com/baeldung/springdoc/demo/controller/SwaggerController.java
index 79c35e025e..bffe0659a6 100644
--- a/spring-boot-modules/spring-boot-swagger-springfox/src/main/java/com/baeldung/springdoc/demo/controller/SwaggerController.java
+++ b/spring-boot-modules/spring-boot-swagger-springfox/src/main/java/com/baeldung/springdoc/demo/controller/SwaggerController.java
@@ -8,6 +8,6 @@ public class SwaggerController {
@RequestMapping("/myproject")
public String getRedirectUrl() {
- return "redirect:swagger-ui.html";
+ return "redirect:swagger-ui/";
}
}
\ No newline at end of file
diff --git a/spring-cloud-modules/pom.xml b/spring-cloud-modules/pom.xml
index a098bc90a9..729dd8eaf1 100644
--- a/spring-cloud-modules/pom.xml
+++ b/spring-cloud-modules/pom.xml
@@ -39,7 +39,7 @@
spring-cloud-archaius
spring-cloud-functions
spring-cloud-vault
- spring-cloud-security
+
spring-cloud-task
spring-cloud-zuul
spring-cloud-zuul-fallback
diff --git a/spring-cloud-modules/spring-cloud-bus/spring-cloud-bus-server/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-bus/spring-cloud-bus-server/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..6fc9dc1151
--- /dev/null
+++ b/spring-cloud-modules/spring-cloud-bus/spring-cloud-bus-server/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-modules/spring-cloud-functions/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-functions/src/test/resources/logback-test.xml
index 8d4771e308..41283752a9 100644
--- a/spring-cloud-modules/spring-cloud-functions/src/test/resources/logback-test.xml
+++ b/spring-cloud-modules/spring-cloud-functions/src/test/resources/logback-test.xml
@@ -6,6 +6,8 @@
+
+
diff --git a/spring-cloud-modules/spring-cloud-security/auth-client/src/main/java/com/baeldung/filters/SimpleFilter.java b/spring-cloud-modules/spring-cloud-security/auth-client/src/main/java/com/baeldung/filters/SimpleFilter.java
index 98e25ac9c4..4204588428 100644
--- a/spring-cloud-modules/spring-cloud-security/auth-client/src/main/java/com/baeldung/filters/SimpleFilter.java
+++ b/spring-cloud-modules/spring-cloud-security/auth-client/src/main/java/com/baeldung/filters/SimpleFilter.java
@@ -1,12 +1,13 @@
package com.baeldung.filters;
import javax.servlet.http.HttpServletRequest;
-import com.netflix.zuul.context.RequestContext;
-import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.netflix.zuul.ZuulFilter;
+import com.netflix.zuul.context.RequestContext;
+
public class SimpleFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
@@ -31,7 +32,8 @@ public class SimpleFilter extends ZuulFilter {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
- log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
+ log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL()
+ .toString()));
return null;
}
diff --git a/spring-cloud-modules/spring-cloud-security/auth-resource/pom.xml b/spring-cloud-modules/spring-cloud-security/auth-resource/pom.xml
index 9362a71931..b4e29fce49 100644
--- a/spring-cloud-modules/spring-cloud-security/auth-resource/pom.xml
+++ b/spring-cloud-modules/spring-cloud-security/auth-resource/pom.xml
@@ -33,6 +33,21 @@
spring-security-jwt
${spring-jwt.version}
+
+ com.sun.xml.bind
+ jaxb-core
+ ${jaxb-core.version}
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb-api.version}
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ ${jaxb-impl.version}
+
diff --git a/spring-cloud-modules/spring-cloud-security/auth-server/pom.xml b/spring-cloud-modules/spring-cloud-security/auth-server/pom.xml
index 234d9cde78..8c14b8fa74 100644
--- a/spring-cloud-modules/spring-cloud-security/auth-server/pom.xml
+++ b/spring-cloud-modules/spring-cloud-security/auth-server/pom.xml
@@ -35,6 +35,21 @@
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
+
+ com.sun.xml.bind
+ jaxb-core
+ ${jaxb-core.version}
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb-api.version}
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ ${jaxb-impl.version}
+
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-security/pom.xml b/spring-cloud-modules/spring-cloud-security/pom.xml
index ad6421384e..72d1d6cbfc 100644
--- a/spring-cloud-modules/spring-cloud-security/pom.xml
+++ b/spring-cloud-modules/spring-cloud-security/pom.xml
@@ -34,6 +34,9 @@
2021.0.3
+ 2.3.0.1
+ 2.3.1
+ 2.3.1
\ No newline at end of file
diff --git a/spring-core-2/pom.xml b/spring-core-2/pom.xml
index f6142cffb0..2d11cc2124 100644
--- a/spring-core-2/pom.xml
+++ b/spring-core-2/pom.xml
@@ -149,7 +149,7 @@
org.apache.maven.plugins
maven-war-plugin
- ${maven.version}
+ ${maven-war-plugin.version}
false
@@ -166,7 +166,7 @@
3.6
2.1.0
3.22.0-GA
- 3.2.2
+ 3.2.2
\ No newline at end of file
diff --git a/spring-core-4/pom.xml b/spring-core-4/pom.xml
index 2d11cc701b..fb544e29fd 100644
--- a/spring-core-4/pom.xml
+++ b/spring-core-4/pom.xml
@@ -74,7 +74,7 @@
org.apache.commons
commons-text
- ${apache-commons-text.version}
+ ${commons-text.version}
@@ -84,7 +84,7 @@
4.0.2
4.0.0
1.3.2
- 1.10.0
+ 1.10.0
\ No newline at end of file
diff --git a/spring-credhub/pom.xml b/spring-credhub/pom.xml
index 4604833d0b..defe378b6b 100644
--- a/spring-credhub/pom.xml
+++ b/spring-credhub/pom.xml
@@ -27,7 +27,7 @@
org.springframework.credhub
spring-credhub-starter
- 2.2.0
+ ${spring-credhub-starter.version}
com.google.code.gson
@@ -36,8 +36,7 @@
- 8
- 8
+ 2.2.0
UTF-8
diff --git a/spring-ejb-modules/ejb-beans/pom.xml b/spring-ejb-modules/ejb-beans/pom.xml
index 6bfbb42a14..94f7963ad6 100644
--- a/spring-ejb-modules/ejb-beans/pom.xml
+++ b/spring-ejb-modules/ejb-beans/pom.xml
@@ -66,12 +66,12 @@
org.apache.activemq
activemq-broker
- ${activemq.broker.version}
+ ${activemq-broker.version}
org.apache.activemq.tooling
activemq-junit
- ${activemq.junit.version}
+ ${activemq-junit.version}
test
@@ -187,8 +187,8 @@
8.2.1.Final
3.2
5.2.3.RELEASE
- 5.16.3
- 5.16.3
+ 5.16.3
+ 5.16.3
2.21.0
2.8
8.2.1.Final
diff --git a/spring-exceptions/src/main/java/com/baeldung/ex/beancreationexception/cause9/Config.java b/spring-exceptions/src/main/java/com/baeldung/ex/beancreationexception/cause9/Config.java
new file mode 100644
index 0000000000..ef182c04b6
--- /dev/null
+++ b/spring-exceptions/src/main/java/com/baeldung/ex/beancreationexception/cause9/Config.java
@@ -0,0 +1,19 @@
+package com.baeldung.ex.beancreationexception.cause9;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class Config {
+
+ @Autowired
+ BeanFactory beanFactory;
+
+ @Bean
+ public BeanB beanB() {
+ beanFactory.getBean("beanA");
+ return new BeanB();
+ }
+}
diff --git a/spring-kafka-2/pom.xml b/spring-kafka-2/pom.xml
index 76a82f6000..0bca20447d 100644
--- a/spring-kafka-2/pom.xml
+++ b/spring-kafka-2/pom.xml
@@ -53,7 +53,7 @@
org.testcontainers
junit-jupiter
- ${testcontainers-kafka.version}
+ ${testcontainers-junit-jupiter.version}
test
@@ -65,6 +65,7 @@
1.16.2
+ 1.16.2
\ No newline at end of file
diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml
index c013be32e3..7ff7a9710a 100644
--- a/spring-kafka/pom.xml
+++ b/spring-kafka/pom.xml
@@ -26,12 +26,12 @@
org.springframework.boot
spring-boot-starter-actuator
- 3.0.5
+ ${spring-boot-starter-actuator.version}
io.micrometer
micrometer-registry-prometheus
- 1.10.5
+ ${micrometer-registry-prometheus.version}
org.springframework.kafka
@@ -90,6 +90,8 @@
+ 3.0.5
+ 1.10.5
1.16.2
diff --git a/spring-katharsis/pom.xml b/spring-katharsis/pom.xml
index b836a42bca..595cde5109 100644
--- a/spring-katharsis/pom.xml
+++ b/spring-katharsis/pom.xml
@@ -33,7 +33,7 @@
io.katharsis
katharsis-spring
- ${katharsis.version}
+ ${katharsis-spring.version}
org.apache.commons
@@ -132,7 +132,7 @@
- 3.0.2
+ 3.0.2
0.9.10
1.6.1
diff --git a/spring-mobile/pom.xml b/spring-mobile/pom.xml
index f810159eb7..d96faf3274 100644
--- a/spring-mobile/pom.xml
+++ b/spring-mobile/pom.xml
@@ -37,24 +37,16 @@
org.apache.maven.plugins
maven-war-plugin
- ${maven-war-plugin.version}
org.apache.maven.plugins
maven-compiler-plugin
- ${maven-compiler-plugin.version}
-
- ${maven.compiler.source}
- ${maven.compiler.target}
-
1.1.5.RELEASE
- 11
- 11
\ No newline at end of file
diff --git a/spring-pulsar/pom.xml b/spring-pulsar/pom.xml
index df1959c84e..05debcab1c 100644
--- a/spring-pulsar/pom.xml
+++ b/spring-pulsar/pom.xml
@@ -27,7 +27,7 @@
org.springframework.pulsar
spring-pulsar-spring-boot-starter
- 0.2.0
+ ${spring-pulsar-spring-boot-starter.version}
@@ -46,4 +46,8 @@
+
+ 0.2.0
+
+
diff --git a/spring-reactive-modules/pom.xml b/spring-reactive-modules/pom.xml
index dd827d796e..61a3c3d17d 100644
--- a/spring-reactive-modules/pom.xml
+++ b/spring-reactive-modules/pom.xml
@@ -18,7 +18,6 @@
spring-reactive-data
- spring-reactive-data-2
spring-reactive-2
spring-reactive-3
spring-reactive-client
diff --git a/spring-reactive-modules/spring-reactive-2/README.md b/spring-reactive-modules/spring-reactive-2/README.md
index a6a4c4f5d0..dbaebc370e 100644
--- a/spring-reactive-modules/spring-reactive-2/README.md
+++ b/spring-reactive-modules/spring-reactive-2/README.md
@@ -9,4 +9,4 @@ This module contains articles about reactive Spring Boot.
- [Backpressure Mechanism in Spring WebFlux](https://www.baeldung.com/spring-webflux-backpressure)
- [Exploring the Spring 5 WebFlux URL Matching](https://www.baeldung.com/spring-5-mvc-url-matching)
- [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header)
-- More articles: [[<-- prev]](../spring-5-reactive) [[next -->]](../spring-5-reactive-3)
+- More articles: [[<-- prev]](../spring-reactive) [[next -->]](../spring-reactive-3)
diff --git a/spring-reactive-modules/spring-reactive-3/README.md b/spring-reactive-modules/spring-reactive-3/README.md
index 631763fa59..4dbaa93226 100644
--- a/spring-reactive-modules/spring-reactive-3/README.md
+++ b/spring-reactive-modules/spring-reactive-3/README.md
@@ -8,4 +8,4 @@ This module contains articles about reactive Spring Boot.
- [Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuators)
- [Reactive WebSockets with Spring 5](https://www.baeldung.com/spring-5-reactive-websockets)
- [A Guide to Spring Session Reactive Support: WebSession](https://www.baeldung.com/spring-session-reactive)
-- More articles: [[<-- prev]](../spring-5-reactive-2)
+- More articles: [[<-- prev]](../spring-reactive-2)
diff --git a/spring-reactive-modules/spring-reactive-client-2/README.md b/spring-reactive-modules/spring-reactive-client-2/README.md
index 04fe3c8f42..6b6a480f46 100644
--- a/spring-reactive-modules/spring-reactive-client-2/README.md
+++ b/spring-reactive-modules/spring-reactive-client-2/README.md
@@ -8,4 +8,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles
- [Limiting the Requests per Second With WebClient](https://www.baeldung.com/spring-webclient-limit-requests-per-second)
- [Stream Large Byte[] to File With WebClient](https://www.baeldung.com/webclient-stream-large-byte-array-to-file)
-- More articles: [[<-- prev]](../spring-5-reactive-client)
+- More articles: [[<-- prev]](../spring-reactive-client)
diff --git a/spring-reactive-modules/spring-reactive-client/README.md b/spring-reactive-modules/spring-reactive-client/README.md
index fc67a4f16e..ae72dc0e4a 100644
--- a/spring-reactive-modules/spring-reactive-client/README.md
+++ b/spring-reactive-modules/spring-reactive-client/README.md
@@ -13,4 +13,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Upload a File with WebClient](https://www.baeldung.com/spring-webclient-upload-file)
- [How to Get Response Body When Testing the Status Code in WebFlux WebClient](https://www.baeldung.com/spring-webclient-get-response-body)
- [Spring Boot FeignClient vs. WebClient](https://www.baeldung.com/spring-boot-feignclient-vs-webclient)
-- More articles: [[next -->]](../spring-5-reactive-client-2)
+- More articles: [[next -->]](../spring-reactive-client-2)
diff --git a/spring-reactive-modules/spring-reactive-data-2/README.md b/spring-reactive-modules/spring-reactive-data-2/README.md
deleted file mode 100644
index c13171cbc6..0000000000
--- a/spring-reactive-modules/spring-reactive-data-2/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-## Spring Data Reactive Project
-
-This module contains articles about reactive Spring Boot Data
-
-### The Course
-
-The "REST With Spring" Classes: http://bit.ly/restwithspring
-
-### Relevant Articles
-- [Pagination in Spring Webflux and Spring Data Reactive](https://www.baeldung.com/spring-data-webflux-pagination)
diff --git a/spring-reactive-modules/spring-reactive-data-2/pom.xml b/spring-reactive-modules/spring-reactive-data-2/pom.xml
deleted file mode 100644
index 64ce278973..0000000000
--- a/spring-reactive-modules/spring-reactive-data-2/pom.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
- 4.0.0
- spring-reactive-data-2
- spring-reactive-data-2
- jar
-
-
- com.baeldung.spring.reactive
- spring-reactive-modules
- 1.0.0-SNAPSHOT
-
-
-
- UTF-8
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-webflux
-
-
- org.springframework.boot
- spring-boot-starter-data-r2dbc
-
-
- org.springframework
- spring-webflux
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- com.h2database
- h2
- runtime
-
-
- io.r2dbc
- r2dbc-h2
- runtime
-
-
- org.projectlombok
- lombok
- true
-
-
- io.projectreactor
- reactor-test
- test
-
-
- javax.validation
- validation-api
- 2.0.1.Final
-
-
-
-
\ No newline at end of file
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/resources/application.properties b/spring-reactive-modules/spring-reactive-data-2/src/main/resources/application.properties
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/spring-reactive-modules/spring-reactive-data/README.md b/spring-reactive-modules/spring-reactive-data/README.md
index cafd0c502f..259ab0be62 100644
--- a/spring-reactive-modules/spring-reactive-data/README.md
+++ b/spring-reactive-modules/spring-reactive-data/README.md
@@ -3,7 +3,9 @@
This module contains articles about reactive Spring Boot Data
### The Course
+
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles
-- [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc)
\ No newline at end of file
+- [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc)
+- [Pagination in Spring Webflux and Spring Data Reactive](https://www.baeldung.com/spring-data-webflux-pagination)
diff --git a/spring-reactive-modules/spring-reactive-data/pom.xml b/spring-reactive-modules/spring-reactive-data/pom.xml
index 91c4dca6e8..03ea440b4f 100644
--- a/spring-reactive-modules/spring-reactive-data/pom.xml
+++ b/spring-reactive-modules/spring-reactive-data/pom.xml
@@ -1,10 +1,10 @@
-
4.0.0
spring-reactive-data
- spring-reactive-data
+ spring-reactive-data-2
jar
@@ -13,17 +13,9 @@
1.0.0-SNAPSHOT
-
-
-
- org.apache.logging.log4j
- log4j-bom
- ${log4j2.version}
- import
- pom
-
-
-
+
+ UTF-8
+
@@ -31,13 +23,16 @@
spring-boot-starter-web
- org.projectlombok
- lombok
+ org.springframework.boot
+ spring-boot-starter-webflux
- io.projectreactor
- reactor-test
- test
+ org.springframework.boot
+ spring-boot-starter-data-r2dbc
+
+
+ org.springframework
+ spring-webflux
org.springframework.boot
@@ -45,12 +40,29 @@
test
- org.springframework.boot
- spring-boot-starter-webflux
+ com.h2database
+ h2
+ runtime
- org.springframework.data
- spring-data-r2dbc
+ io.r2dbc
+ r2dbc-h2
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
io.r2dbc
@@ -58,17 +70,4 @@
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
- 2.17.1
-
-
\ No newline at end of file
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/PaginationApplication.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/PaginationApplication.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/PaginationApplication.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/PaginationApplication.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/config/CustomWebMvcConfigurationSupport.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/config/CustomWebMvcConfigurationSupport.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/config/CustomWebMvcConfigurationSupport.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/config/CustomWebMvcConfigurationSupport.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/config/DatabaseConfig.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/config/DatabaseConfig.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/config/DatabaseConfig.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/config/DatabaseConfig.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/controller/ProductPaginationController.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/controller/ProductPaginationController.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/controller/ProductPaginationController.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/controller/ProductPaginationController.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/model/Product.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/model/Product.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/model/Product.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/model/Product.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/repository/ProductRepository.java b/spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/repository/ProductRepository.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/java/com/baeldung/pagination/repository/ProductRepository.java
rename to spring-reactive-modules/spring-reactive-data/src/main/java/com/baeldung/pagination/repository/ProductRepository.java
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/main/resources/init.sql b/spring-reactive-modules/spring-reactive-data/src/main/resources/init.sql
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/main/resources/init.sql
rename to spring-reactive-modules/spring-reactive-data/src/main/resources/init.sql
diff --git a/spring-reactive-modules/spring-reactive-data-2/src/test/java/com/baeldung/pagination/controller/ProductPaginationControllerIntegrationTest.java b/spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/pagination/controller/ProductPaginationControllerIntegrationTest.java
similarity index 100%
rename from spring-reactive-modules/spring-reactive-data-2/src/test/java/com/baeldung/pagination/controller/ProductPaginationControllerIntegrationTest.java
rename to spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/pagination/controller/ProductPaginationControllerIntegrationTest.java
diff --git a/spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/SpringContextTest.java b/spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/r2dbc/SpringContextTest.java
similarity index 85%
rename from spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/SpringContextTest.java
rename to spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/r2dbc/SpringContextTest.java
index dc7bcd1e37..facefd3144 100644
--- a/spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/SpringContextTest.java
+++ b/spring-reactive-modules/spring-reactive-data/src/test/java/com/baeldung/r2dbc/SpringContextTest.java
@@ -1,12 +1,10 @@
-package com.baeldung;
+package com.baeldung.r2dbc;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
-import com.baeldung.r2dbc.R2dbcApplication;
-
@RunWith(SpringRunner.class)
@SpringBootTest(classes = R2dbcApplication.class)
public class SpringContextTest {
diff --git a/spring-reactive-modules/spring-reactive-security/pom.xml b/spring-reactive-modules/spring-reactive-security/pom.xml
index bd74202437..cf34b21083 100644
--- a/spring-reactive-modules/spring-reactive-security/pom.xml
+++ b/spring-reactive-modules/spring-reactive-security/pom.xml
@@ -76,12 +76,12 @@
io.reactivex.rxjava2
rxjava
- ${rxjava-version}
+ ${rxjava.version}
io.projectreactor
reactor-test
- ${project-reactor-test}
+ ${project-reactor-test.version}
test
@@ -110,11 +110,11 @@
1.0.1.RELEASE
- 2.1.12
+ 2.1.12
1.1.3
1.0
1.0
- 3.1.6.RELEASE
+ 3.1.6.RELEASE
\ No newline at end of file
diff --git a/spring-remoting-modules/pom.xml b/spring-remoting-modules/pom.xml
index 41d77c2969..8a5990fd1d 100644
--- a/spring-remoting-modules/pom.xml
+++ b/spring-remoting-modules/pom.xml
@@ -43,16 +43,10 @@
org.apache.maven.plugins
maven-compiler-plugin
${maven-compiler-plugin.version}
-
- ${maven.compiler.source}
- ${maven.compiler.target}
-
- 11
- 11
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-core-2/pom.xml b/spring-security-modules/spring-security-core-2/pom.xml
index e540d7bc01..5d77098869 100644
--- a/spring-security-modules/spring-security-core-2/pom.xml
+++ b/spring-security-modules/spring-security-core-2/pom.xml
@@ -15,6 +15,10 @@
../../parent-boot-2
+
+ 5.8.4
+
+
org.springframework.boot
@@ -49,6 +53,16 @@
org.springframework.security
spring-security-test
+
+ org.springframework.security
+ spring-security-web
+ ${spring.security.version}
+
+
+ org.springframework.security
+ spring-security-core
+ ${spring.security.version}
+
@@ -100,4 +114,4 @@
-
\ No newline at end of file
+
diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/HttpSecurityConfig.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/HttpSecurityConfig.java
new file mode 100644
index 0000000000..d6361255e5
--- /dev/null
+++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/HttpSecurityConfig.java
@@ -0,0 +1,31 @@
+package com.baeldung.httpsecurityvswebsecurity;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+@EnableWebSecurity
+public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // Given: HttpSecurity configured
+
+ http.authorizeRequests()
+ .antMatchers("/public/**").permitAll()
+ .antMatchers("/admin/**").hasRole("ADMIN")
+ .anyRequest().authenticated()
+ .and()
+ .formLogin()
+ .loginPage("/login")
+ .permitAll()
+ .and()
+ .logout()
+ .permitAll();
+
+ // When: Accessing specific URLs
+ // Then: Access is granted based on defined rules
+ }
+}
diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/WebSecurityConfig.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/WebSecurityConfig.java
new file mode 100644
index 0000000000..46a82918aa
--- /dev/null
+++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/httpsecurityvswebsecurity/WebSecurityConfig.java
@@ -0,0 +1,35 @@
+package com.baeldung.httpsecurityvswebsecurity;
+
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private UserDetailsService userDetailsService;
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth
+ .userDetailsService(userDetailsService)
+ .passwordEncoder(new BCryptPasswordEncoder());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ .antMatchers("/")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .formLogin();
+ }
+}
diff --git a/spring-security-modules/spring-security-core/pom.xml b/spring-security-modules/spring-security-core/pom.xml
index 0eb70c0853..03d7030057 100644
--- a/spring-security-modules/spring-security-core/pom.xml
+++ b/spring-security-modules/spring-security-core/pom.xml
@@ -100,4 +100,4 @@
-
\ No newline at end of file
+
diff --git a/spring-security-modules/spring-security-ldap/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-security-ldap/src/test/java/com/baeldung/SpringContextTest.java
index a15ca31980..62b1ae908b 100644
--- a/spring-security-modules/spring-security-ldap/src/test/java/com/baeldung/SpringContextTest.java
+++ b/spring-security-modules/spring-security-ldap/src/test/java/com/baeldung/SpringContextTest.java
@@ -1,6 +1,5 @@
package com.baeldung;
-import com.baeldung.SampleLDAPApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
diff --git a/spring-security-modules/spring-security-oauth2-testing/pom.xml b/spring-security-modules/spring-security-oauth2-testing/pom.xml
index 93348cb48c..45fcf9bcce 100644
--- a/spring-security-modules/spring-security-oauth2-testing/pom.xml
+++ b/spring-security-modules/spring-security-oauth2-testing/pom.xml
@@ -14,7 +14,7 @@
../../parent-boot-3
- 6.1.0
+ 7.1.10
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java
index 500d876bc4..716900ea51 100644
--- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java
@@ -1,7 +1,8 @@
package com.baeldung;
+import static org.springframework.security.config.Customizer.withDefaults;
+
import java.nio.charset.Charset;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -27,6 +28,7 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import org.springframework.stereotype.Service;
@@ -34,6 +36,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
+import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@SpringBootApplication
@@ -46,68 +49,66 @@ public class ReactiveResourceServerApplication {
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
- public class SecurityConfig {
+ static class SecurityConfig {
@Bean
- SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, Converter>> authoritiesConverter) {
- http.oauth2ResourceServer()
- .jwt()
- .jwtAuthenticationConverter(jwt -> authoritiesConverter.convert(jwt)
- .map(authorities -> new JwtAuthenticationToken(jwt, authorities)));
- http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
- .csrf()
- .disable();
- http.exceptionHandling()
- .accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal()
- .flatMap(principal -> {
+ SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
+ http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(withDefaults()));
+ http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance());
+ http.csrf(csrf -> csrf.disable());
+ http.exceptionHandling(eh -> eh
+ .accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal().flatMap(principal -> {
final var response = exchange.getResponse();
- response.setStatusCode(principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED : HttpStatus.FORBIDDEN);
- response.getHeaders()
- .setContentType(MediaType.TEXT_PLAIN);
+ response.setStatusCode(
+ principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED
+ : HttpStatus.FORBIDDEN);
+ response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
final var dataBufferFactory = response.bufferFactory();
- final var buffer = dataBufferFactory.wrap(ex.getMessage()
- .getBytes(Charset.defaultCharset()));
+ final var buffer = dataBufferFactory.wrap(ex.getMessage().getBytes(Charset.defaultCharset()));
return response.writeWith(Mono.just(buffer))
- .doOnError(error -> DataBufferUtils.release(buffer));
- }));
+ .doOnError(error -> DataBufferUtils.release(buffer));
+ })));
- http.authorizeExchange()
- .pathMatchers("/secured-route")
- .hasRole("AUTHORIZED_PERSONNEL")
- .anyExchange()
- .authenticated();
+ // @formatter:off
+ http.authorizeExchange(req -> req
+ .pathMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL").anyExchange()
+ .authenticated());
+ // @formatter:on
return http.build();
}
- static interface AuthoritiesConverter extends Converter>> {
+ static interface ReactiveJwtAuthoritiesConverter extends Converter> {
}
@Bean
- AuthoritiesConverter realmRoles2AuthoritiesConverter() {
+ ReactiveJwtAuthoritiesConverter realmRoles2AuthoritiesConverter() {
return (Jwt jwt) -> {
- final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access"))
- .orElse(Map.of());
+ final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of());
@SuppressWarnings("unchecked")
final var roles = (List) realmRoles.getOrDefault("roles", List.of());
- return Mono.just(roles.stream()
- .map(SimpleGrantedAuthority::new)
- .map(GrantedAuthority.class::cast)
- .toList());
+ return Flux.fromStream(roles.stream()).map(SimpleGrantedAuthority::new)
+ .map(GrantedAuthority.class::cast);
};
}
+
+ @Bean
+ ReactiveJwtAuthenticationConverter authenticationConverter(
+ Converter> authoritiesConverter) {
+ final var authenticationConverter = new ReactiveJwtAuthenticationConverter();
+ authenticationConverter.setPrincipalClaimName(StandardClaimNames.PREFERRED_USERNAME);
+ authenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
+ return authenticationConverter;
+ }
}
@Service
public static class MessageService {
public Mono greet() {
- return ReactiveSecurityContextHolder.getContext()
- .map(ctx -> {
- final var who = (JwtAuthenticationToken) ctx.getAuthentication();
- final var claims = who.getTokenAttributes();
- return "Hello %s! You are granted with %s.".formatted(claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME, claims.get(StandardClaimNames.SUB)), who.getAuthorities());
- })
- .switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty")));
+ return ReactiveSecurityContextHolder.getContext().map(ctx -> {
+ final var who = (JwtAuthenticationToken) ctx.getAuthentication();
+ return "Hello %s! You are granted with %s.".formatted(who.getName(), who.getAuthorities());
+ }).switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty")));
}
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
@@ -118,26 +119,23 @@ public class ReactiveResourceServerApplication {
@RestController
@RequiredArgsConstructor
- public class GreetingController {
+ public static class GreetingController {
private final MessageService messageService;
@GetMapping("/greet")
public Mono> greet() {
- return messageService.greet()
- .map(ResponseEntity::ok);
+ return messageService.greet().map(ResponseEntity::ok);
}
@GetMapping("/secured-route")
public Mono> securedRoute() {
- return messageService.getSecret()
- .map(ResponseEntity::ok);
+ return messageService.getSecret().map(ResponseEntity::ok);
}
@GetMapping("/secured-method")
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
public Mono> securedMethod() {
- return messageService.getSecret()
- .map(ResponseEntity::ok);
+ return messageService.getSecret().map(ResponseEntity::ok);
}
}
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
index 97893bc1fb..c13a20ca38 100644
--- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
@@ -3,28 +3,49 @@ package com.baeldung;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.util.stream.Stream;
+
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
-import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
+import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.baeldung.ReactiveResourceServerApplication.MessageService;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.baeldung.ReactiveResourceServerApplication.SecurityConfig;
+import com.c4_soft.springaddons.security.oauth2.test.AuthenticationFactoriesTestConf;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithJwt;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.ParameterizedAuthentication;
-@Import({ MessageService.class })
+@Import({ MessageService.class, SecurityConfig.class })
+@ImportAutoConfiguration(AuthenticationFactoriesTestConf.class)
@ExtendWith(SpringExtension.class)
-@EnableReactiveMethodSecurity
+@TestInstance(Lifecycle.PER_CLASS)
class MessageServiceUnitTest {
@Autowired
MessageService messageService;
+ @Autowired
+ WithJwt.AuthenticationFactory authFactory;
+
+ @MockBean
+ ReactiveJwtDecoder jwtDecoder;
+
/*----------------------------------------------------------------------------*/
/* greet() */
/* Expects a JwtAuthenticationToken to be retrieved from the security-context */
@@ -43,10 +64,12 @@ class MessageServiceUnitTest {
.block());
}
- @Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenSecurityContextIsPopulatedWithJwtAuthenticationToken_whenGreet_thenReturnGreetingWithPreferredUsernameAndAuthorities() {
- assertEquals("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].", messageService.greet()
+ @ParameterizedTest
+ @MethodSource("allIdentities")
+ void givenUserIsAuthenticated_whenGreet_thenReturnGreetingWithPreferredUsernameAndAuthorities(@ParameterizedAuthentication Authentication auth) {
+ final var jwt = (JwtAuthenticationToken) auth;
+ final var expected = "Hello %s! You are granted with %s.".formatted(jwt.getTokenAttributes().get(StandardClaimNames.PREFERRED_USERNAME), auth.getAuthorities());
+ assertEquals(expected, messageService.greet()
.block());
}
@@ -70,17 +93,25 @@ class MessageServiceUnitTest {
}
@Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenReturnSecret() {
+ @WithJwt("ch4mpy.json")
+ void givenUserIsCh4mpy_whenGetSecret_thenReturnSecret() {
assertEquals("Only authorized personnel can read that", messageService.getSecret()
.block());
}
@Test
- @WithMockJwtAuth(authorities = { "admin" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenThrowsAccessDeniedException() {
+ @WithJwt("tonton-pirate.json")
+ void givenUserIsTontonPirate_whenGetSecret_thenThrowsAccessDeniedException() {
assertThrows(AccessDeniedException.class, () -> messageService.getSecret()
.block());
}
+ /*--------------------------------------------*/
+ /* methodSource returning all test identities */
+ /*--------------------------------------------*/
+ private Stream allIdentities() {
+ final var authentications = authFactory.authenticationsFrom("ch4mpy.json", "tonton-pirate.json").toList();
+ return authentications.stream();
+ }
+
}
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/ReactiveResourceServerApplicationIntegrationTest.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/ReactiveResourceServerApplicationIntegrationTest.java
index 1ee6fc7e87..d6bfbf4e2d 100644
--- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/ReactiveResourceServerApplicationIntegrationTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/ReactiveResourceServerApplicationIntegrationTest.java
@@ -8,8 +8,8 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.reactive.server.WebTestClient;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithJwt;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockAuthentication;
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureWebTestClient
@@ -33,7 +33,7 @@ class ReactiveResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
+ @WithJwt("ch4mpy.json")
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
api.get()
.uri("/greet")
@@ -60,7 +60,7 @@ class ReactiveResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
api.get()
.uri("/secured-route")
@@ -72,7 +72,7 @@ class ReactiveResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
api.get()
.uri("/secured-route")
@@ -97,7 +97,7 @@ class ReactiveResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
api.get()
.uri("/secured-method")
@@ -109,7 +109,7 @@ class ReactiveResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
api.get()
.uri("/secured-method")
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
index 6f55f287d8..f31bbe3ae8 100644
--- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
@@ -5,16 +5,19 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.core.Authentication;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.baeldung.ReactiveResourceServerApplication.GreetingController;
import com.baeldung.ReactiveResourceServerApplication.MessageService;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockAuthentication;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.AuthenticationSource;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.ParameterizedAuthentication;
import reactor.core.publisher.Mono;
@@ -28,115 +31,88 @@ class SpringAddonsGreetingControllerUnitTest {
WebTestClient api;
/*-----------------------------------------------------------------------------*/
- /* /greet */
- /* This end-point secured with ".anyRequest().authenticated()" in SecurityConf */
+ /* /greet */
+ /*
+ * This end-point secured with ".anyRequest().authenticated()" in SecurityConf
+ */
/*-----------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenRequestIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception {
- api.get()
- .uri("/greet")
- .exchange()
- .expectStatus()
- .isUnauthorized();
+ api.get().uri("/greet").exchange().expectStatus().isUnauthorized();
}
- @Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
+ @ParameterizedTest
+ @AuthenticationSource({
+ @WithMockAuthentication(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, name = "ch4mpy"),
+ @WithMockAuthentication(authorities = { "uncle", "PIRATE" }, name = "tonton-pirate") })
+ void givenUserIsAuthenticated_whenGetGreet_thenOk(@ParameterizedAuthentication Authentication auth) throws Exception {
final var greeting = "Whatever the service returns";
when(messageService.greet()).thenReturn(Mono.just(greeting));
- api.get()
- .uri("/greet")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .isEqualTo(greeting);
+ api.get().uri("/greet").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo(greeting);
verify(messageService, times(1)).greet();
}
/*---------------------------------------------------------------------------------------------------------------------*/
- /* /secured-route */
- /* This end-point is secured with ".requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")" in SecurityConf */
+ /* /secured-route */
+ /*
+ * This end-point is secured with
+ * ".requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")" in
+ * SecurityConf
+ */
/*---------------------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenRequestIsAnonymous_whenGetSecuredRoute_thenUnauthorized() throws Exception {
- api.get()
- .uri("/secured-route")
- .exchange()
- .expectStatus()
- .isUnauthorized();
+ api.get().uri("/secured-route").exchange().expectStatus().isUnauthorized();
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
final var secret = "Secret!";
when(messageService.getSecret()).thenReturn(Mono.just(secret));
- api.get()
- .uri("/secured-route")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .isEqualTo(secret);
+ api.get().uri("/secured-route").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo(secret);
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
- api.get()
- .uri("/secured-route")
- .exchange()
- .expectStatus()
- .isForbidden();
+ api.get().uri("/secured-route").exchange().expectStatus().isForbidden();
}
/*---------------------------------------------------------------------------------------------------------*/
- /* /secured-method */
- /* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
+ /* /secured-method */
+ /*
+ * This end-point is secured with
+ * "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method
+ */
/*---------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenRequestIsAnonymous_whenGetSecuredMethod_thenUnauthorized() throws Exception {
- api.get()
- .uri("/secured-method")
- .exchange()
- .expectStatus()
- .isUnauthorized();
+ api.get().uri("/secured-method").exchange().expectStatus().isUnauthorized();
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
final var secret = "Secret!";
when(messageService.getSecret()).thenReturn(Mono.just(secret));
- api.get()
- .uri("/secured-method")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .isEqualTo(secret);
+ api.get().uri("/secured-method").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo(secret);
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
- api.get()
- .uri("/secured-method")
- .exchange()
- .expectStatus()
- .isForbidden();
+ api.get().uri("/secured-method").exchange().expectStatus().isForbidden();
}
}
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json
new file mode 100644
index 0000000000..22f7bb2cea
--- /dev/null
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json
@@ -0,0 +1,15 @@
+{
+ "iss": "https://localhost:8443/realms/master",
+ "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b",
+ "iat": 1695992542,
+ "exp": 1695992642,
+ "preferred_username": "ch4mpy",
+ "realm_access": {
+ "roles": [
+ "admin",
+ "ROLE_AUTHORIZED_PERSONNEL"
+ ]
+ },
+ "email": "ch4mp@c4-soft.com",
+ "scope": "openid email"
+}
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json
new file mode 100644
index 0000000000..13a422f6fd
--- /dev/null
+++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json
@@ -0,0 +1,15 @@
+{
+ "iss": "https://localhost:8443/realms/master",
+ "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558",
+ "iat": 1695992551,
+ "exp": 1695992651,
+ "preferred_username": "tonton-pirate",
+ "realm_access": {
+ "roles": [
+ "uncle",
+ "PIRATE"
+ ]
+ },
+ "email": "tonton-pirate@c4-soft.com",
+ "scope": "openid email"
+}
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java
index a30c60eab0..8258955afe 100644
--- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java
@@ -1,5 +1,7 @@
package com.baeldung;
+import static org.springframework.security.config.Customizer.withDefaults;
+
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -23,8 +25,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -43,56 +47,52 @@ public class ServletResourceServerApplication {
@EnableWebSecurity
static class SecurityConf {
@Bean
- SecurityFilterChain filterChain(HttpSecurity http, Converter> authoritiesConverter) throws Exception {
- http.oauth2ResourceServer()
- .jwt()
- .jwtAuthenticationConverter(jwt -> new JwtAuthenticationToken(jwt, authoritiesConverter.convert(jwt)));
- http.sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- .csrf()
- .disable();
- http.exceptionHandling()
- .authenticationEntryPoint((request, response, authException) -> {
- response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
- response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
- });
+ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(withDefaults()));
+ http.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
+ http.csrf(csrf -> csrf.disable());
+ http.exceptionHandling(eh -> eh.authenticationEntryPoint((request, response, authException) -> {
+ response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Bearer realm=\"Restricted Content\"");
+ response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
+ }));
- http.authorizeHttpRequests()
- .requestMatchers("/secured-route")
- .hasRole("AUTHORIZED_PERSONNEL")
- .anyRequest()
- .authenticated();
+ // @formatter:off
+ http.authorizeHttpRequests(req -> req
+ .requestMatchers(new AntPathRequestMatcher("/secured-route")).hasRole("AUTHORIZED_PERSONNEL")
+ .anyRequest().authenticated());
+ // @formatter:on
return http.build();
}
- static interface AuthoritiesConverter extends Converter> {
+ static interface JwtAuthoritiesConverter extends Converter> {
}
@Bean
- AuthoritiesConverter realmRoles2AuthoritiesConverter() {
+ JwtAuthoritiesConverter realmRoles2AuthoritiesConverter() {
return (Jwt jwt) -> {
- final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access"))
- .orElse(Map.of());
+ final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of());
@SuppressWarnings("unchecked")
final var roles = (List) realmRoles.getOrDefault("roles", List.of());
- return roles.stream()
- .map(SimpleGrantedAuthority::new)
- .map(GrantedAuthority.class::cast)
- .toList();
+ return roles.stream().map(SimpleGrantedAuthority::new).map(GrantedAuthority.class::cast).toList();
};
}
+
+ @Bean
+ JwtAuthenticationConverter authenticationConverter(Converter> authoritiesConverter) {
+ final var authenticationConverter = new JwtAuthenticationConverter();
+ authenticationConverter.setPrincipalClaimName(StandardClaimNames.PREFERRED_USERNAME);
+ authenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
+ return authenticationConverter;
+ }
}
@Service
public static class MessageService {
public String greet() {
- final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext()
- .getAuthentication();
- final var claims = who.getTokenAttributes();
- return "Hello %s! You are granted with %s.".formatted(claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME, claims.get(StandardClaimNames.SUB)), who.getAuthorities());
+ final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
+ return "Hello %s! You are granted with %s.".formatted(who.getName(), who.getAuthorities());
}
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
index 3c608d226e..ca237fb888 100644
--- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/MessageServiceUnitTest.java
@@ -3,28 +3,49 @@ package com.baeldung;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.util.stream.Stream;
+
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
-import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
+import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.baeldung.ServletResourceServerApplication.MessageService;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.baeldung.ServletResourceServerApplication.SecurityConf;
+import com.c4_soft.springaddons.security.oauth2.test.AuthenticationFactoriesTestConf;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithJwt;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.ParameterizedAuthentication;
-@Import({ MessageService.class })
+@Import({ MessageService.class, SecurityConf.class })
+@ImportAutoConfiguration(AuthenticationFactoriesTestConf.class)
@ExtendWith(SpringExtension.class)
-@EnableMethodSecurity
+@TestInstance(Lifecycle.PER_CLASS)
class MessageServiceUnitTest {
@Autowired
MessageService messageService;
+ @Autowired
+ WithJwt.AuthenticationFactory authFactory;
+
+ @MockBean
+ JwtDecoder jwtDecoder;
+
/*----------------------------------------------------------------------------*/
/* greet() */
/* Expects a JwtAuthenticationToken to be retrieved from the security-context */
@@ -41,10 +62,12 @@ class MessageServiceUnitTest {
assertThrows(AccessDeniedException.class, () -> messageService.getSecret());
}
- @Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenSecurityContextIsPopulatedWithJwtAuthenticationToken_whenGreet_thenReturnGreetingWithPreferredUsernameAndAuthorities() {
- assertEquals("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].", messageService.greet());
+ @ParameterizedTest
+ @MethodSource("allIdentities")
+ void givenUserIsAuthenticated_whenGreet_thenReturnGreetingWithPreferredUsernameAndAuthorities(@ParameterizedAuthentication Authentication auth) {
+ final var jwt = (JwtAuthenticationToken) auth;
+ final var expected = "Hello %s! You are granted with %s.".formatted(jwt.getTokenAttributes().get(StandardClaimNames.PREFERRED_USERNAME), auth.getAuthorities());
+ assertEquals(expected, messageService.greet());
}
@Test
@@ -65,15 +88,22 @@ class MessageServiceUnitTest {
}
@Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenReturnSecret() {
+ @WithJwt("ch4mpy.json")
+ void givenUserIsCh4mpy_whenGetSecret_thenReturnSecret() {
assertEquals("Only authorized personnel can read that", messageService.getSecret());
}
@Test
- @WithMockJwtAuth(authorities = { "admin" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenThrowsAccessDeniedException() {
+ @WithJwt("tonton-pirate.json")
+ void givenUserIsTontonPirate_whenGetSecret_thenThrowsAccessDeniedException() {
assertThrows(AccessDeniedException.class, () -> messageService.getSecret());
}
+ /*--------------------------------------------*/
+ /* methodSource returning all test identities */
+ /*--------------------------------------------*/
+ private Stream allIdentities() {
+ final var authentications = authFactory.authenticationsFrom("ch4mpy.json", "tonton-pirate.json").toList();
+ return authentications.stream();
+ }
}
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/ServletResourceServerApplicationIntegrationTest.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/ServletResourceServerApplicationIntegrationTest.java
index 5bb539741f..4f2fe51787 100644
--- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/ServletResourceServerApplicationIntegrationTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/ServletResourceServerApplicationIntegrationTest.java
@@ -12,8 +12,8 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.servlet.MockMvc;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithJwt;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockAuthentication;
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
@@ -34,7 +34,7 @@ class ServletResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
+ @WithJwt("ch4mpy.json")
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
api.perform(get("/greet"))
.andExpect(status().isOk())
@@ -54,7 +54,7 @@ class ServletResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
api.perform(get("/secured-route"))
.andExpect(status().isOk())
@@ -62,7 +62,7 @@ class ServletResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
api.perform(get("/secured-route"))
.andExpect(status().isForbidden());
@@ -81,7 +81,7 @@ class ServletResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
+ @WithMockAuthentication("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
api.perform(get("/secured-method"))
.andExpect(status().isOk())
@@ -89,7 +89,7 @@ class ServletResourceServerApplicationIntegrationTest {
}
@Test
- @WithMockJwtAuth("admin")
+ @WithMockAuthentication("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
api.perform(get("/secured-method"))
.andExpect(status().isForbidden());
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
index 9162768930..2534d9919a 100644
--- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java
@@ -8,16 +8,19 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.core.Authentication;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.servlet.MockMvc;
import com.baeldung.ServletResourceServerApplication.GreetingController;
import com.baeldung.ServletResourceServerApplication.MessageService;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
-import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockAuthentication;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.AuthenticationSource;
+import com.c4_soft.springaddons.security.oauth2.test.annotations.parameterized.ParameterizedAuthentication;
@WebMvcTest(controllers = GreetingController.class, properties = { "server.ssl.enabled=false" })
class SpringAddonsGreetingControllerUnitTest {
@@ -40,9 +43,11 @@ class SpringAddonsGreetingControllerUnitTest {
.andExpect(status().isUnauthorized());
}
- @Test
- @WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
- void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
+ @ParameterizedTest
+ @AuthenticationSource({
+ @WithMockAuthentication(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, name = "ch4mpy"),
+ @WithMockAuthentication(authorities = { "uncle", "PIRATE" }, name = "tonton-pirate") })
+ void givenUserIsAuthenticated_whenGetGreet_thenOk(@ParameterizedAuthentication Authentication auth) throws Exception {
final var greeting = "Whatever the service returns";
when(messageService.greet()).thenReturn(greeting);
@@ -66,7 +71,7 @@ class SpringAddonsGreetingControllerUnitTest {
}
@Test
- @WithMockJwtAuth({ "admin", "ROLE_AUTHORIZED_PERSONNEL" })
+ @WithMockAuthentication({ "admin", "ROLE_AUTHORIZED_PERSONNEL" })
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
final var secret = "Secret!";
when(messageService.getSecret()).thenReturn(secret);
@@ -77,7 +82,7 @@ class SpringAddonsGreetingControllerUnitTest {
}
@Test
- @WithMockJwtAuth({ "admin" })
+ @WithMockAuthentication({ "admin" })
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
api.perform(get("/secured-route"))
.andExpect(status().isForbidden());
@@ -96,7 +101,7 @@ class SpringAddonsGreetingControllerUnitTest {
}
@Test
- @WithMockJwtAuth({ "admin", "ROLE_AUTHORIZED_PERSONNEL" })
+ @WithMockAuthentication({ "admin", "ROLE_AUTHORIZED_PERSONNEL" })
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
final var secret = "Secret!";
when(messageService.getSecret()).thenReturn(secret);
@@ -107,7 +112,7 @@ class SpringAddonsGreetingControllerUnitTest {
}
@Test
- @WithMockJwtAuth(authorities = { "admin" })
+ @WithMockAuthentication({ "admin" })
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
api.perform(get("/secured-method"))
.andExpect(status().isForbidden());
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json
new file mode 100644
index 0000000000..22f7bb2cea
--- /dev/null
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json
@@ -0,0 +1,15 @@
+{
+ "iss": "https://localhost:8443/realms/master",
+ "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b",
+ "iat": 1695992542,
+ "exp": 1695992642,
+ "preferred_username": "ch4mpy",
+ "realm_access": {
+ "roles": [
+ "admin",
+ "ROLE_AUTHORIZED_PERSONNEL"
+ ]
+ },
+ "email": "ch4mp@c4-soft.com",
+ "scope": "openid email"
+}
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json
new file mode 100644
index 0000000000..13a422f6fd
--- /dev/null
+++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json
@@ -0,0 +1,15 @@
+{
+ "iss": "https://localhost:8443/realms/master",
+ "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558",
+ "iat": 1695992551,
+ "exp": 1695992651,
+ "preferred_username": "tonton-pirate",
+ "realm_access": {
+ "roles": [
+ "uncle",
+ "PIRATE"
+ ]
+ },
+ "email": "tonton-pirate@c4-soft.com",
+ "scope": "openid email"
+}
\ No newline at end of file
diff --git a/spring-shell/pom.xml b/spring-shell/pom.xml
index 952920fd1e..24fe5b0fb6 100644
--- a/spring-shell/pom.xml
+++ b/spring-shell/pom.xml
@@ -28,7 +28,6 @@
org.apache.maven.plugins
maven-war-plugin
- ${maven-war-plugin.version}
src/main/webapp
false
diff --git a/spring-soap/pom.xml b/spring-soap/pom.xml
index 594eb3dd19..6c49f1f39c 100644
--- a/spring-soap/pom.xml
+++ b/spring-soap/pom.xml
@@ -34,7 +34,7 @@
jakarta.xml.bind
jakarta.xml.bind-api
- 4.0.0
+ ${jakarta.xml.bind-api.version}
@@ -58,7 +58,7 @@
org.codehaus.mojo
jaxb2-maven-plugin
- 3.1.0
+ ${jaxb2-maven-plugin.version}
xjc
@@ -79,7 +79,7 @@
org.jvnet.jaxb2.maven2
maven-jaxb2-plugin
- 0.15.3
+ ${maven-jaxb2-plugin.version}
@@ -103,5 +103,8 @@
17
+ 4.0.0
+ 3.1.0
+ 0.15.3
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
index c529951b07..b57a014a8f 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
@@ -29,22 +29,22 @@
org.hibernate
hibernate-validator
- 6.0.10.Final
+ ${hibernate-validator.version}
javax.validation
validation-api
- 2.0.1.Final
+ ${validation-api.version}
org.openapitools
openapi-generator
- 3.3.4
+ ${openapi-generator.version}
com.fasterxml.jackson.core
jackson-databind
- 2.10.0.pr3
+ ${jackson-databind.version}
org.springdoc
@@ -62,7 +62,7 @@
org.openapitools
openapi-generator-maven-plugin
- 5.1.0
+ ${openapi-generator-maven-plugin.version}
@@ -97,6 +97,11 @@
3.0.0
2.17.1
1.7.0
+ 6.0.10.Final
+ 2.0.1.Final
+ 3.3.4
+ 2.10.0.pr3
+ 5.1.0
\ No newline at end of file
diff --git a/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml
index f125018fb0..ee2c86238a 100644
--- a/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml
+++ b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml
@@ -34,55 +34,55 @@
io.swagger
swagger-annotations
- ${swagger-annotations-version}
+ ${swagger-annotations.version}
com.google.code.findbugs
jsr305
- 3.0.2
+ ${findbugs-jsr305.version}
org.springframework
spring-web
- ${spring-web-version}
+ ${spring-web.version}
com.fasterxml.jackson.core
jackson-core
- ${jackson-version}
+ ${jackson.version}
com.fasterxml.jackson.core
jackson-annotations
- ${jackson-version}
+ ${jackson.version}
com.fasterxml.jackson.core
jackson-databind
- ${jackson-version}
+ ${jackson.version}
com.fasterxml.jackson.jaxrs
jackson-jaxrs-json-provider
- ${jackson-version}
+ ${jackson.version}
org.openapitools
jackson-databind-nullable
- ${jackson-databind-nullable-version}
+ ${jackson-databind-nullable.version}
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
- ${jackson-version}
+ ${jackson.version}
com.github.joschi.jackson
jackson-datatype-threetenbp
- ${jackson-threetenbp-version}
+ ${jackson-threetenbp.version}
@@ -94,7 +94,7 @@
javax.annotation
javax.annotation-api
- 1.3.2
+ ${javax.annotation-api.version}
@@ -103,7 +103,7 @@
org.apache.maven.plugins
maven-enforcer-plugin
- 3.0.0-M1
+ ${maven-enforcer-plugin.version}
enforce-maven
@@ -123,7 +123,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.12
+ ${maven-surefire-plugin.version}
@@ -154,7 +154,7 @@
org.apache.maven.plugins
maven-jar-plugin
- 2.2
+ ${maven-jar-plugin.version}
@@ -169,7 +169,7 @@
org.codehaus.mojo
build-helper-maven-plugin
- 1.10
+ ${build-helper-maven-plugin.version}
add_sources
@@ -200,7 +200,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.6.1
+ ${maven-compiler-plugin.version}
1.8
1.8
@@ -209,7 +209,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 2.10.4
+ ${maven-javadoc-plugin.version}
attach-javadocs
@@ -222,7 +222,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.2.1
+ ${maven-source-plugin.version}
attach-sources
@@ -243,7 +243,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.5
+ ${maven-gpg-plugin.version}
sign-artifacts
@@ -260,14 +260,25 @@
- 1.5.22
- 4.3.9.RELEASE
- 2.11.1
+ 1.5.22
+ 4.3.9.RELEASE
+ 3.0.2
+ 2.11.1
- 0.2.1
- 2.9.10
- 1.0.0
+ 0.2.1
+ 2.9.10
+ 1.0.0
5.8.1
+ 1.3.2
+
+ 3.0.0-M1
+ 2.12
+ 2.2
+ 1.10
+ 3.6.1
+ 2.10.4
+ 2.2.1
+ 1.5
\ No newline at end of file
diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
index b2e97c7a49..35f4978411 100644
--- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
+++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
@@ -40,13 +40,13 @@
io.swagger
swagger-annotations
- ${swagger-annotations-version}
+ ${swagger-annotations.version}
org.springframework
spring-web
- ${spring-web-version}
+ ${spring-web.version}
@@ -77,12 +77,12 @@
joda-time
joda-time
- ${jodatime-version}
+ ${jodatime.version}
javax.annotation
javax.annotation-api
- 1.3.2
+ ${javax.annotation-api.version}
@@ -189,9 +189,10 @@
- 1.5.15
- 4.3.9.RELEASE
- 2.9.9
+ 1.5.15
+ 4.3.9.RELEASE
+ 2.9.9
+ 1.3.2
2.2
1.5
2.2.1
diff --git a/spring-vault/pom.xml b/spring-vault/pom.xml
index 60a5ee18f2..b3690c7b7f 100644
--- a/spring-vault/pom.xml
+++ b/spring-vault/pom.xml
@@ -36,7 +36,7 @@
org.springframework.vault
spring-vault-core
- ${spring.vault.core.version}
+ ${spring-vault-core.version}
org.springframework.data
@@ -69,18 +69,20 @@
software.amazon.awssdk
auth
- 2.20.140
+ ${auth.version}
org.springframework.cloud
spring-cloud-starter-vault-config
- 3.1.3
+ ${spring-cloud-starter-vault-config.version}
- 2.3.4
+ 2.3.4
+ 2.20.140
+ 3.1.3
17
diff --git a/spring-web-modules/pom.xml b/spring-web-modules/pom.xml
index d513822ea3..9f03b83392 100644
--- a/spring-web-modules/pom.xml
+++ b/spring-web-modules/pom.xml
@@ -52,6 +52,7 @@
spring-thymeleaf-4
spring-thymeleaf-5
spring-web-url
+ spring-thymeleaf-attributes
\ No newline at end of file
diff --git a/spring-web-modules/spring-mvc-basics-5/pom.xml b/spring-web-modules/spring-mvc-basics-5/pom.xml
index c957d669bd..e0d603e303 100644
--- a/spring-web-modules/spring-mvc-basics-5/pom.xml
+++ b/spring-web-modules/spring-mvc-basics-5/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-2
+ parent-boot-3
0.0.1-SNAPSHOT
- ../../parent-boot-2
+ ../../parent-boot-3
@@ -30,8 +30,14 @@
tomcat-embed-jasper
- javax.servlet
- jstl
+ jakarta.servlet.jsp.jstl
+ jakarta.servlet.jsp.jstl-api
+ ${jakarta.servlet.jsp.jstl}
+
+
+ org.glassfish.web
+ jakarta.servlet.jsp.jstl
+ ${jakarta.servlet.jsp.jstl}
org.springframework.boot
@@ -53,6 +59,11 @@
jaxb-runtime
${jaxb-runtime.version}
+
+ io.rest-assured
+ rest-assured
+ ${io.rest-assured.version}
+
@@ -73,6 +84,8 @@
1.3.2
2.7.0
2.3.5
+ 2.0.0
+ 3.0.0
\ No newline at end of file
diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/jsonargs/JsonArgumentResolver.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/jsonargs/JsonArgumentResolver.java
index 3cb01dae32..94b8d12107 100644
--- a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/jsonargs/JsonArgumentResolver.java
+++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/jsonargs/JsonArgumentResolver.java
@@ -3,7 +3,7 @@ package com.baeldung.jsonargs;
import java.io.IOException;
import java.util.Objects;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java
index 0ec3c5c374..2dacfe87d9 100644
--- a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java
+++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/modelattribute/Employee.java
@@ -1,6 +1,6 @@
package com.baeldung.modelattribute;
-import javax.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Employee {
diff --git a/testing-modules/testing-libraries-2/pom.xml b/testing-modules/testing-libraries-2/pom.xml
index 4cc3ea8428..717ccac2b2 100644
--- a/testing-modules/testing-libraries-2/pom.xml
+++ b/testing-modules/testing-libraries-2/pom.xml
@@ -53,6 +53,30 @@
${system-stubs.version}
test
+
+ uk.org.webcompere
+ system-stubs-testng
+ ${system-stubs.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.junit-pioneer
+ junit-pioneer
+ ${junit.pioneer.version}
+ test
+
+
+ org.testng
+ testng
+ ${testng.version}
+ test
+
@@ -127,6 +151,9 @@
--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
+
+ YES
+
@@ -142,7 +169,10 @@
0.8.6
1.19.0
1.0.0
- 1.1.0
+ 2.1.3
+ 7.8.0
+ 3.24.2
+ 2.1.0
\ No newline at end of file
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesByAbstractionUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesByAbstractionUnitTest.java
new file mode 100644
index 0000000000..0ac0603c64
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesByAbstractionUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class EnvironmentVariablesByAbstractionUnitTest {
+
+ @FunctionalInterface
+ interface GetEnv {
+ String get(String name);
+ }
+
+ static class ReadsEnvironment {
+ private GetEnv getEnv;
+
+ public ReadsEnvironment(GetEnv getEnv) {
+ this.getEnv = getEnv;
+ }
+
+ public String whatOs() {
+ return getEnv.get("OS");
+ }
+ }
+
+ @Test
+ void givenFakeOs_thenCanReadIt() {
+ Map fakeEnv = new HashMap<>();
+ fakeEnv.put("OS", "MacDowsNix");
+
+ ReadsEnvironment reader = new ReadsEnvironment(fakeEnv::get);
+ assertThat(reader.whatOs()).isEqualTo("MacDowsNix");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetByJUnitPioneerUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetByJUnitPioneerUnitTest.java
new file mode 100644
index 0000000000..02081a6598
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetByJUnitPioneerUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.ClearEnvironmentVariable;
+import org.junitpioneer.jupiter.SetEnvironmentVariable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SetEnvironmentVariable(key = "pioneer", value = "is pioneering")
+class EnvironmentVariablesSetByJUnitPioneerUnitTest {
+
+ @Test
+ void givenEnvironmentVariableIsSetForClass_thenVariableCanBeRead() {
+ assertThat(System.getenv("pioneer")).isEqualTo("is pioneering");
+ }
+
+ @ClearEnvironmentVariable(key = "pioneer")
+ @Test
+ void givenEnvironmentVariableIsClear_thenItIsNotSet() {
+ assertThat(System.getenv("pioneer")).isNull();
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetDirectlyUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetDirectlyUnitTest.java
new file mode 100644
index 0000000000..61a3ca3c2e
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSetDirectlyUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_16)
+class EnvironmentVariablesSetDirectlyUnitTest {
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ Class> classOfMap = System.getenv().getClass();
+ Field field = classOfMap.getDeclaredField("m");
+ field.setAccessible(true);
+ Map writeableEnvironmentVariables = (Map)field.get(System.getenv());
+
+ writeableEnvironmentVariables.put("baeldung", "has set an environment variable");
+ }
+
+ @Test
+ void givenEnvironmentVariableWasSet_thenCanReadIt() {
+ assertThat(System.getenv("baeldung")).isEqualTo("has set an environment variable");
+ }
+
+ @Test
+ void givenEnvironmentVariableSetBySurefire_thenCanReadIt() {
+ assertThat(System.getenv("SET_BY_SUREFIRE")).isEqualTo("YES");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemLambdaUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemLambdaUnitTest.java
new file mode 100644
index 0000000000..050bebddfd
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemLambdaUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class EnvironmentVariablesSystemLambdaUnitTest {
+
+ @Test
+ void givenSetEnvironmentVariablesInTest_thenCanBeRead() throws Exception {
+ withEnvironmentVariable("system lambda", "in test")
+ .execute(() -> {
+ assertThat(System.getenv("system lambda")).isEqualTo("in test");
+ });
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemRulesUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemRulesUnitTest.java
new file mode 100644
index 0000000000..44ebb1be71
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemRulesUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EnvironmentVariablesSystemRulesUnitTest {
+ @Rule
+ public EnvironmentVariables environmentVariablesRule = new EnvironmentVariables();
+
+ @Before
+ public void before() {
+ environmentVariablesRule.set("system rules", "works");
+ }
+
+ @Test
+ public void givenEnvironmentVariable_thenCanReadIt() {
+ assertThat(System.getenv("system rules")).isEqualTo("works");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit4UnitTest.java
new file mode 100644
index 0000000000..efb0ba5598
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit4UnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import uk.org.webcompere.systemstubs.rules.EnvironmentVariablesRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EnvironmentVariablesSystemStubsJUnit4UnitTest {
+ @Rule
+ public EnvironmentVariablesRule environmentVariablesRule =
+ new EnvironmentVariablesRule("system stubs", "initializes variable");
+
+ @Test
+ public void givenEnvironmentSetUpInObject_thenCanReadIt() {
+ assertThat(System.getenv("system stubs")).isEqualTo("initializes variable");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit5UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit5UnitTest.java
new file mode 100644
index 0000000000..1304e4921a
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsJUnit5UnitTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.environmentvariablesfortest;
+
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
+import uk.org.webcompere.systemstubs.jupiter.SystemStub;
+import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@ExtendWith(SystemStubsExtension.class)
+class EnvironmentVariablesSystemStubsJUnit5UnitTest {
+
+ @SystemStub
+ private EnvironmentVariables environmentVariables;
+
+ @BeforeEach
+ void beforeEach() {
+ environmentVariables.set("systemstubs", "creates stub objects");
+ }
+
+ @Test
+ void givenEnvironmentVariableHasBeenSet_thenCanReadIt() {
+ assertThat(System.getenv("systemstubs")).isEqualTo("creates stub objects");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkClassScopeEnvironmentUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkClassScopeEnvironmentUnitTest.java
new file mode 100644
index 0000000000..9e9421c3f1
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkClassScopeEnvironmentUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class EnvironmentVariablesSystemStubsNoFrameworkClassScopeEnvironmentUnitTest {
+ private static EnvironmentVariables environmentVariables = new EnvironmentVariables();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ environmentVariables.set("system stubs", "in test");
+ environmentVariables.setup();
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ environmentVariables.teardown();
+ }
+
+ @Test
+ void givenSetEnvironmentVariablesBeforeAll_thenCanBeRead() throws Exception {
+ assertThat(System.getenv("system stubs")).isEqualTo("in test");
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkUnitTest.java
new file mode 100644
index 0000000000..2e7a92b85f
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsNoFrameworkUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariables;
+
+class EnvironmentVariablesSystemStubsNoFrameworkUnitTest {
+
+ @Test
+ void givenSetEnvironmentVariablesInTest_thenCanBeRead() throws Exception {
+ withEnvironmentVariables("system stubs", "in test")
+ .execute(() -> {
+ assertThat(System.getenv("system stubs")).isEqualTo("in test");
+ });
+ }
+}
diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsTestNGUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsTestNGUnitTest.java
new file mode 100644
index 0000000000..61ca76a8b0
--- /dev/null
+++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/environmentvariablesfortest/EnvironmentVariablesSystemStubsTestNGUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.environmentvariablesfortest;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
+import uk.org.webcompere.systemstubs.testng.SystemStub;
+import uk.org.webcompere.systemstubs.testng.SystemStubsListener;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Listeners(SystemStubsListener.class)
+public class EnvironmentVariablesSystemStubsTestNGUnitTest {
+ @SystemStub
+ private EnvironmentVariables setEnvironment;
+
+ @BeforeClass
+ public void beforeAll() {
+ setEnvironment.set("testng", "has environment variables");
+ }
+
+ @Test
+ public void givenEnvironmentVariableWasSet_thenItCanBeRead() {
+ assertThat(System.getenv("testng")).isEqualTo("has environment variables");
+ }
+
+}
diff --git a/xml-2/pom.xml b/xml-2/pom.xml
index 7d10f36042..0f94588ba0 100644
--- a/xml-2/pom.xml
+++ b/xml-2/pom.xml
@@ -46,6 +46,16 @@
underscore
${underscore.version}
+
+ org.apache.xmlbeans
+ xmlbeans
+ 5.0.2
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.12.4
+
@@ -74,4 +84,4 @@
1.89
-
\ No newline at end of file
+
diff --git a/xml-2/src/main/resources/log4j2.xml b/xml-2/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..f022ab633b
--- /dev/null
+++ b/xml-2/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xml-2/src/test/java/com/baeldung/xml/xml2string/XMLObjectToStringUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/xml2string/XMLObjectToStringUnitTest.java
new file mode 100644
index 0000000000..0afa3424f3
--- /dev/null
+++ b/xml-2/src/test/java/com/baeldung/xml/xml2string/XMLObjectToStringUnitTest.java
@@ -0,0 +1,87 @@
+package com.baeldung.xml2string;
+
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.junit.Test;
+import org.junit.Before;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.StringWriter;
+
+import static org.junit.Assert.assertTrue;
+
+public class XMLObjectToStringUnitTest {
+ private Document document;
+
+ @Before
+ public void setup() throws ParserConfigurationException {
+// Create a DocumentBuilder
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+// Create a new Document
+ document = builder.newDocument();
+
+// Create the root element
+ Element rootElement = document.createElement("root");
+ document.appendChild(rootElement);
+
+// Create child elements
+ Element childElement1 = document.createElement("child1");
+ Element childElement2 = document.createElement("child2");
+
+// Add text content to the child elements
+ childElement1.appendChild(document.createTextNode("This is child element 1"));
+ childElement2.appendChild(document.createTextNode("This is child element 2"));
+
+// Append child elements to the root element
+ rootElement.appendChild(childElement1);
+ rootElement.appendChild(childElement2);
+ }
+
+ @Test
+ public void givenXMLDocument_whenUsingTransformer_thenConvertXMLToString() throws TransformerException {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ StringWriter stringWriter = new StringWriter();
+ transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
+ String result = stringWriter.toString();
+
+ assertTrue(result.contains(""));
+ assertTrue(result.contains("This is child element 1"));
+ assertTrue(result.contains("This is child element 2"));
+ }
+
+ @Test
+ public void givenXMLDocument_whenUsingXmlBeans_thenConvertXMLToString() {
+ try {
+
+ XmlObject xmlObject = XmlObject.Factory.parse(document);
+
+ XmlOptions options = new XmlOptions();
+ options.setSavePrettyPrint();
+ options.setUseDefaultNamespace();
+ options.setSaveAggressiveNamespaces();
+
+ String xmlString = xmlObject.xmlText(options);
+
+ xmlString = "" + xmlString;
+
+ assertTrue(xmlString.contains(""));
+ assertTrue(xmlString.contains("This is child element 1"));
+ assertTrue(xmlString.contains("This is child element 2"));
+ } catch (XmlException e) {
+ e.printStackTrace();
+ }
+ }
+}