From 2e41874a5c9aca865e0cb7cf00fb84b748527833 Mon Sep 17 00:00:00 2001
From: 3hsan <56245694+ehsansasanian@users.noreply.github.com>
Date: Fri, 5 May 2023 10:47:57 +0200
Subject: [PATCH 01/20] JAVA-16946: comment spring-jooq module from
persistence-modules. (#13951)
---
persistence-modules/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 46ac9b50f1..ad757d9073 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -107,7 +107,7 @@
spring-jdbc
- spring-jooq
+
spring-mybatis
spring-persistence-simple
From 7e404b3dfbe48f7246037b7230247485d264444b Mon Sep 17 00:00:00 2001
From: Kasra Madadipouya
Date: Fri, 5 May 2023 11:58:11 +0200
Subject: [PATCH 02/20] JAVA-20555 use Java Base64 instead of deprecated Spring
Base64Utils (#13941)
---
.../security/oauth2/UaaTokenEndpointClient.java | 4 ++--
.../web/ManualOauthRequestController.java | 6 ++++--
.../authresolver/AuthResolverIntegrationTest.java | 11 ++++++-----
.../authresolver/AuthResolverIntegrationTest.java | 11 ++++++-----
.../petstore/client/invoker/auth/HttpBasicAuth.java | 5 +++--
.../petstore/client/invoker/auth/HttpBasicAuth.java | 6 +++---
6 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/jhipster-modules/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/security/oauth2/UaaTokenEndpointClient.java b/jhipster-modules/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/security/oauth2/UaaTokenEndpointClient.java
index 01c8febdb2..296e8cf67a 100644
--- a/jhipster-modules/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/security/oauth2/UaaTokenEndpointClient.java
+++ b/jhipster-modules/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/security/oauth2/UaaTokenEndpointClient.java
@@ -5,11 +5,11 @@ import io.github.jhipster.config.JHipsterProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
-import org.springframework.util.Base64Utils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
/**
* Client talking to UAA's token endpoint to do different OAuth2 grants.
@@ -34,7 +34,7 @@ public class UaaTokenEndpointClient extends OAuth2TokenEndpointClientAdapter imp
String clientId = getClientId();
String clientSecret = getClientSecret();
String authorization = clientId + ":" + clientSecret;
- return "Basic " + Base64Utils.encodeToString(authorization.getBytes(StandardCharsets.UTF_8));
+ return "Basic " + Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8));
}
}
diff --git a/spring-reactive-modules/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java b/spring-reactive-modules/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java
index d54d811032..c449a5991e 100644
--- a/spring-reactive-modules/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java
+++ b/spring-reactive-modules/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java
@@ -1,12 +1,13 @@
package com.baeldung.webclient.manualrequest.web;
+import java.util.Base64;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
-import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.BodyInserters;
@@ -41,7 +42,8 @@ public class ManualOauthRequestController {
logger.info("Creating web client...");
Mono resource = client.post()
.uri(tokenUri)
- .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((clientId + ":" + clientSecret).getBytes()))
+ .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder()
+ .encodeToString((clientId + ":" + clientSecret).getBytes()))
.body(BodyInserters.fromFormData(OAuth2ParameterNames.GRANT_TYPE, GrantType.CLIENT_CREDENTIALS.getValue()))
.retrieve()
.bodyToMono(JsonNode.class)
diff --git a/spring-reactive-modules/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java b/spring-reactive-modules/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java
index 691243b3ea..9e0855d086 100644
--- a/spring-reactive-modules/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java
+++ b/spring-reactive-modules/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java
@@ -1,5 +1,7 @@
package com.baeldung.reactive.authresolver;
+import java.util.Base64;
+
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -8,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
-import org.springframework.util.Base64Utils;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class)
@@ -22,7 +23,7 @@ public class AuthResolverIntegrationTest {
testClient
.get()
.uri("/customer/welcome")
- .header("Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes()))
+ .header("Authorization", "Basic " + Base64.getEncoder().encodeToString("customer1:pass1".getBytes()))
.exchange()
.expectStatus()
.isOk();
@@ -33,7 +34,7 @@ public class AuthResolverIntegrationTest {
testClient
.get()
.uri("/customer/welcome")
- .header("Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes()))
+ .header("Authorization", "Basic " + Base64.getEncoder().encodeToString("employee1:pass1".getBytes()))
.exchange()
.expectStatus()
.isUnauthorized();
@@ -44,7 +45,7 @@ public class AuthResolverIntegrationTest {
testClient
.get()
.uri("/employee/welcome")
- .header("Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes()))
+ .header("Authorization", "Basic " + Base64.getEncoder().encodeToString("employee1:pass1".getBytes()))
.exchange()
.expectStatus()
.isOk();
@@ -55,7 +56,7 @@ public class AuthResolverIntegrationTest {
testClient
.get()
.uri("/employee/welcome")
- .header("Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes()))
+ .header("Authorization", "Basic " + Base64.getEncoder().encodeToString("customer1:pass1".getBytes()))
.exchange()
.expectStatus()
.isUnauthorized();
diff --git a/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java b/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java
index c87f8c1a3a..a0bc793a11 100644
--- a/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java
+++ b/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java
@@ -11,13 +11,14 @@ import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import org.springframework.util.Base64Utils;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import java.util.Base64;
+
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -44,7 +45,7 @@ public class AuthResolverIntegrationTest {
this.mockMvc
.perform(get("/customer/welcome")
.header(
- "Authorization", String.format("Basic %s", Base64Utils.encodeToString("customer1:pass1".getBytes()))
+ "Authorization", String.format("Basic %s", Base64.getEncoder().encodeToString("customer1:pass1".getBytes()))
)
)
.andExpect(status().is2xxSuccessful());
@@ -55,7 +56,7 @@ public class AuthResolverIntegrationTest {
this.mockMvc
.perform(get("/customer/welcome")
.header(
- "Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes()))
+ "Authorization", "Basic " + Base64.getEncoder().encodeToString("employee1:pass1".getBytes()))
)
.andExpect(status().isUnauthorized());
}
@@ -65,7 +66,7 @@ public class AuthResolverIntegrationTest {
this.mockMvc
.perform(get("/employee/welcome")
.header(
- "Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes()))
+ "Authorization", "Basic " + Base64.getEncoder().encodeToString("employee1:pass1".getBytes()))
)
.andExpect(status().is2xxSuccessful());
}
@@ -75,7 +76,7 @@ public class AuthResolverIntegrationTest {
this.mockMvc
.perform(get("/employee/welcome")
.header(
- "Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes()))
+ "Authorization", "Basic " + Base64.getEncoder().encodeToString("customer1:pass1".getBytes()))
)
.andExpect(status().isUnauthorized());
}
diff --git a/spring-swagger-codegen/spring-openapi-generator-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java b/spring-swagger-codegen/spring-openapi-generator-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
index 4c1dad6e7c..fea7b0532b 100644
--- a/spring-swagger-codegen/spring-openapi-generator-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
+++ b/spring-swagger-codegen/spring-openapi-generator-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
@@ -1,9 +1,9 @@
package com.baeldung.petstore.client.invoker.auth;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import org.springframework.http.HttpHeaders;
-import org.springframework.util.Base64Utils;
import org.springframework.util.MultiValueMap;
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2020-03-15T06:14:01.568992-05:00[America/Chicago]")
@@ -33,6 +33,7 @@ public class HttpBasicAuth implements Authentication {
return;
}
String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
- headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8)));
+ headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder()
+ .encodeToString(str.getBytes(StandardCharsets.UTF_8)));
}
}
diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java b/spring-swagger-codegen/spring-swagger-codegen-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
index 16c88a4bc6..23c1dbc4c2 100644
--- a/spring-swagger-codegen/spring-swagger-codegen-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
+++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/src/main/java/com/baeldung/petstore/client/invoker/auth/HttpBasicAuth.java
@@ -1,10 +1,9 @@
package com.baeldung.petstore.client.invoker.auth;
-import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import org.springframework.http.HttpHeaders;
-import org.springframework.util.Base64Utils;
import org.springframework.util.MultiValueMap;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2017-08-29T12:04:37.072+02:00")
@@ -34,6 +33,7 @@ public class HttpBasicAuth implements Authentication {
return;
}
String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
- headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8)));
+ headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder()
+ .encodeToString(str.getBytes(StandardCharsets.UTF_8)));
}
}
From f37f777d9373e3f81ded165bbf5d8767282d22da Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 21:41:29 +0800
Subject: [PATCH 03/20] Update README.md
[skip ci]
---
core-java-modules/core-java-perf/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/core-java-modules/core-java-perf/README.md b/core-java-modules/core-java-perf/README.md
index 2f0331f281..c400f1d196 100644
--- a/core-java-modules/core-java-perf/README.md
+++ b/core-java-modules/core-java-perf/README.md
@@ -14,3 +14,4 @@ This module contains articles about performance of Java applications
- [JMX Ports](https://www.baeldung.com/jmx-ports)
- [Calling JMX MBean Method From a Shell Script](https://www.baeldung.com/jmx-mbean-shell-access)
- [External Debugging With JMXTerm](https://www.baeldung.com/java-jmxterm-external-debugging)
+- [Create and Detect Memory Leaks in Java](https://www.baeldung.com/java-create-detect-memory-leaks)
From ab1964f166b176025a1898c2c7aee4988fdcb05e Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 21:48:48 +0800
Subject: [PATCH 04/20] Update README.md
[skip ci]
---
spring-boot-modules/spring-boot-3/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/spring-boot-modules/spring-boot-3/README.md b/spring-boot-modules/spring-boot-3/README.md
index be95ce2830..e99eb79127 100644
--- a/spring-boot-modules/spring-boot-3/README.md
+++ b/spring-boot-modules/spring-boot-3/README.md
@@ -6,3 +6,4 @@
- [Migrate Application From Spring Boot 2 to Spring Boot 3](https://www.baeldung.com/spring-boot-3-migration)
- [Using Java Records with JPA](https://www.baeldung.com/spring-jpa-java-records)
- [HTTP Interface in Spring 6](https://www.baeldung.com/spring-6-http-interface)
+- [Working with Virtual Threads in Spring 6](https://www.baeldung.com/spring-6-virtual-threads)
From 69e5f59d4b6f60a6ab26ca784728545612988834 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:24:09 +0800
Subject: [PATCH 05/20] Update README.md
[skip ci]
---
core-java-modules/core-java-string-operations-5/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/core-java-modules/core-java-string-operations-5/README.md b/core-java-modules/core-java-string-operations-5/README.md
index 94fb7e855e..bbd63d1138 100644
--- a/core-java-modules/core-java-string-operations-5/README.md
+++ b/core-java-modules/core-java-string-operations-5/README.md
@@ -8,3 +8,4 @@
- [Convert String to String Array](https://www.baeldung.com/java-convert-string-to-string-array)
- [String Interpolation in Java](https://www.baeldung.com/java-string-interpolation)
- [Guide to Splitting a String by Whitespace in Java](https://www.baeldung.com/java-splitting-a-string-by-whitespace)
+- [Check if the First Letter of a String Is a Number](https://www.baeldung.com/java-check-if-string-starts-with-number)
From cc061011c75b130132e268307c114aa2836866a4 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:28:38 +0800
Subject: [PATCH 06/20] Update README.md
[skip ci]
---
core-java-modules/core-java-char/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/core-java-modules/core-java-char/README.md b/core-java-modules/core-java-char/README.md
index 5f33aa6914..e4af3121c5 100644
--- a/core-java-modules/core-java-char/README.md
+++ b/core-java-modules/core-java-char/README.md
@@ -4,3 +4,4 @@ This module contains articles about Java Character Class
### Relevant Articles:
- [Character#isAlphabetic vs. Character#isLetter](https://www.baeldung.com/java-character-isletter-isalphabetic)
+- [Difference Between Java’s “char” and “String”](https://www.baeldung.com/java-char-vs-string)
From 7720c03dbf9c5ead745a2ec7ca044993c7a5ed10 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:37:21 +0800
Subject: [PATCH 07/20] Update README.md
[skip ci]
---
spring-boot-modules/spring-boot-libraries-2/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/spring-boot-modules/spring-boot-libraries-2/README.md b/spring-boot-modules/spring-boot-libraries-2/README.md
index fbba6ad62c..5c6b93469d 100644
--- a/spring-boot-modules/spring-boot-libraries-2/README.md
+++ b/spring-boot-modules/spring-boot-libraries-2/README.md
@@ -10,4 +10,5 @@ This module contains articles about various Spring Boot libraries
- [Scanning Java Annotations At Runtime](https://www.baeldung.com/java-scan-annotations-runtime)
- [Guide to Resilience4j With Spring Boot](https://www.baeldung.com/spring-boot-resilience4j)
- [Using OpenAI ChatGPT APIs in Spring Boot](https://www.baeldung.com/spring-boot-chatgpt-api-openai)
+- [Introduction to Spring Modulith](https://www.baeldung.com/spring-modulith)
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-libraries)
From 93348fff6060a4d25fc1db6e417eb7163fd25089 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:42:22 +0800
Subject: [PATCH 08/20] Update README.md
[skip ci]
---
persistence-modules/hibernate-mapping-2/README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/persistence-modules/hibernate-mapping-2/README.md b/persistence-modules/hibernate-mapping-2/README.md
index 7a811e17cf..4fba6691cf 100644
--- a/persistence-modules/hibernate-mapping-2/README.md
+++ b/persistence-modules/hibernate-mapping-2/README.md
@@ -4,4 +4,5 @@ This module contains articles about Hibernate Mappings.
### Relevant articles
-- [Hibernate Many to Many Annotation Tutorial](https://www.baeldung.com/hibernate-many-to-many)
\ No newline at end of file
+- [Hibernate Many to Many Annotation Tutorial](https://www.baeldung.com/hibernate-many-to-many)
+- [Boolean Converters in Hibernate 6](https://www.baeldung.com/java-hibernate-6-boolean-converters)
From e47d956d5e641087a8e87abd66e32edfd1f28427 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:48:25 +0800
Subject: [PATCH 09/20] Update README.md
[skip ci]
---
testing-modules/selenium-junit-testng/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/testing-modules/selenium-junit-testng/README.md b/testing-modules/selenium-junit-testng/README.md
index 4d9834c6f5..e262fb326f 100644
--- a/testing-modules/selenium-junit-testng/README.md
+++ b/testing-modules/selenium-junit-testng/README.md
@@ -10,6 +10,7 @@
- [Handle Browser Tabs With Selenium](https://www.baeldung.com/java-handle-browser-tabs-selenium)
- [Implicit Wait vs Explicit Wait in Selenium Webdriver](https://www.baeldung.com/selenium-implicit-explicit-wait)
- [StaleElementReferenceException in Selenium](https://www.baeldung.com/selenium-staleelementreferenceexception)
+- [Retrieve the Value of an HTML Input in Selenium WebDriver](https://www.baeldung.com/java-selenium-html-input-value)
#### Notes:
- to run the live tests for the article *Fixing Selenium WebDriver Executable Path Error*, follow the manual setup described
From 2a750529ff6fbfbdb2f395ad839b7dca87f75b0a Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:51:11 +0800
Subject: [PATCH 10/20] Update README.md
[skip ci]
---
algorithms-modules/algorithms-miscellaneous-7/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md
index 53c218a40c..ab07d655f9 100644
--- a/algorithms-modules/algorithms-miscellaneous-7/README.md
+++ b/algorithms-modules/algorithms-miscellaneous-7/README.md
@@ -2,4 +2,5 @@
- [Algorithm to Identify and Validate a Credit Card Number](https://www.baeldung.com/java-validate-cc-number)
- [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)
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
From 73ab237379e701a4ccc5be90d9518d21fa7204e6 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Fri, 5 May 2023 23:58:06 +0800
Subject: [PATCH 11/20] Update README.md
[skip ci]
---
persistence-modules/spring-data-jpa-repo-3/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/persistence-modules/spring-data-jpa-repo-3/README.md b/persistence-modules/spring-data-jpa-repo-3/README.md
index dc33900736..d3782eb1e6 100644
--- a/persistence-modules/spring-data-jpa-repo-3/README.md
+++ b/persistence-modules/spring-data-jpa-repo-3/README.md
@@ -4,4 +4,5 @@ This module contains articles about Spring Data JPA.
### Relevant Articles:
- [New CRUD Repository Interfaces in Spring Data 3](https://www.baeldung.com/spring-data-3-crud-repository-interfaces)
+- [How to Persist a List of String in JPA?](https://www.baeldung.com/java-jpa-persist-string-list)
- More articles: [[<-- prev]](../spring-data-jpa-repo-2)
From bb7a389e0140162b7fb1048a3f1016d50ebead28 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Sat, 6 May 2023 00:09:33 +0800
Subject: [PATCH 12/20] Update README.md
[skip ci]
---
core-java-modules/core-java-arrays-operations-basic/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/core-java-modules/core-java-arrays-operations-basic/README.md b/core-java-modules/core-java-arrays-operations-basic/README.md
index 2e1268e00c..eed64c0cae 100644
--- a/core-java-modules/core-java-arrays-operations-basic/README.md
+++ b/core-java-modules/core-java-arrays-operations-basic/README.md
@@ -11,3 +11,4 @@ This module contains articles about Java array fundamentals. They assume no prev
- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element)
- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end)
- [Initializing a Boolean Array in Java](https://www.baeldung.com/java-initializing-boolean-array)
+- [Find the Index of an Element in a Java Array](https://www.baeldung.com/java-array-find-index)
From 35d5f583ac8f41316a274eafd4d932ad3e9b173a Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Sat, 6 May 2023 00:15:22 +0800
Subject: [PATCH 13/20] Update README.md
[skip ci]
---
core-java-modules/core-java-string-operations-5/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/core-java-modules/core-java-string-operations-5/README.md b/core-java-modules/core-java-string-operations-5/README.md
index bbd63d1138..70a4f5607e 100644
--- a/core-java-modules/core-java-string-operations-5/README.md
+++ b/core-java-modules/core-java-string-operations-5/README.md
@@ -9,3 +9,4 @@
- [String Interpolation in Java](https://www.baeldung.com/java-string-interpolation)
- [Guide to Splitting a String by Whitespace in Java](https://www.baeldung.com/java-splitting-a-string-by-whitespace)
- [Check if the First Letter of a String Is a Number](https://www.baeldung.com/java-check-if-string-starts-with-number)
+- [Print “” Quotes Around a String in Java](https://www.baeldung.com/java-string-print-quotes)
From 7d26ae4a5ed1f6e10d095df606f99de422effd24 Mon Sep 17 00:00:00 2001
From: edizor <113095366+edizor@users.noreply.github.com>
Date: Sat, 6 May 2023 00:19:31 +0800
Subject: [PATCH 14/20] Update README.md
[skip ci]
---
core-java-modules/core-java-20/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core-java-modules/core-java-20/README.md b/core-java-modules/core-java-20/README.md
index 7e20469e44..aba4e9e240 100644
--- a/core-java-modules/core-java-20/README.md
+++ b/core-java-modules/core-java-20/README.md
@@ -1,2 +1,2 @@
## Relevant Articles
-- TBD
\ No newline at end of file
+- [Scoped Values in Java 20](https://www.baeldung.com/java-20-scoped-values)
From 3ab60dc3070a173a0827c2d8cf174bf9e3e4491f Mon Sep 17 00:00:00 2001
From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com>
Date: Fri, 5 May 2023 22:25:50 +0200
Subject: [PATCH 15/20] BAEL-6332: Calling Non-Static Method In Static Method
In Java (#13940)
---
.../java/com/baeldung/staticmodifier/Car.java | 4 ++++
.../CallNonStaticMethodUnitTest.java | 21 +++++++++++++++++++
.../baeldung/staticmodifier/CarUnitTest.java | 7 +++++++
3 files changed, 32 insertions(+)
create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmethod/CallNonStaticMethodUnitTest.java
diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticmodifier/Car.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticmodifier/Car.java
index 950f008dcd..1158851fbd 100644
--- a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticmodifier/Car.java
+++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticmodifier/Car.java
@@ -42,6 +42,10 @@ public class Car {
this.engine = engine;
}
+ public static String getCarsInformation(Car car) {
+ return car.getName() + "-" + car.getEngine();
+ }
+
public static void setNumberOfCars(int numberOfCars) {
Car.numberOfCars = numberOfCars;
}
diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmethod/CallNonStaticMethodUnitTest.java b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmethod/CallNonStaticMethodUnitTest.java
new file mode 100644
index 0000000000..1171cb2e7a
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmethod/CallNonStaticMethodUnitTest.java
@@ -0,0 +1,21 @@
+package com.baeldung.staticmethod;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import com.baeldung.staticmodifier.Car;
+
+public class CallNonStaticMethodUnitTest {
+ @AfterClass
+ public static void setUpCarInstance() {
+ Car.setNumberOfCars(0);
+ }
+ @Test
+ public void whenCallingNonStaticMethodInStaticMethodWithInstanceClass_thenSuccess() {
+ Car car = new Car("Jaguar", "V8");
+ assertEquals("Jaguar-V8", Car.getCarsInformation(car));
+ }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmodifier/CarUnitTest.java b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmodifier/CarUnitTest.java
index f55955caa8..68bbe8f0a2 100644
--- a/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmodifier/CarUnitTest.java
+++ b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticmodifier/CarUnitTest.java
@@ -2,9 +2,16 @@ package com.baeldung.staticmodifier;
import static org.junit.Assert.*;
+import org.junit.AfterClass;
import org.junit.Test;
public class CarUnitTest {
+
+ @AfterClass
+ public static void setUpCarInstance() {
+ Car.setNumberOfCars(0);
+ }
+
@Test
public void whenNumberOfCarObjectsInitialized_thenStaticCounterIncreases() {
new Car("Jaguar", "V8");
From dea82bf189c8a34b0f5614f05d34ec789ee490f3 Mon Sep 17 00:00:00 2001
From: Kai Yuan
Date: Sat, 6 May 2023 03:11:54 +0200
Subject: [PATCH 16/20] [BAEL-6485_RM-Punctuation] Remove Punctuation (#13946)
---
.../RemovePunctuationUnitTest.java | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 core-java-modules/core-java-string-operations-5/src/test/java/com/baeldung/delpunctuation/RemovePunctuationUnitTest.java
diff --git a/core-java-modules/core-java-string-operations-5/src/test/java/com/baeldung/delpunctuation/RemovePunctuationUnitTest.java b/core-java-modules/core-java-string-operations-5/src/test/java/com/baeldung/delpunctuation/RemovePunctuationUnitTest.java
new file mode 100644
index 0000000000..751ae0f4bc
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-5/src/test/java/com/baeldung/delpunctuation/RemovePunctuationUnitTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.delpunctuation;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class RemovePunctuationUnitTest {
+ private static final String INPUT = "Its 1 W o r d (!@#$%^&*{}[];':\")<>,.";
+ private static final String EXPECTED = "Its 1 W o r d ";
+
+ private static final String UNICODE_INPUT = "3 March März 三月 březen маршировать (!@#$%^&*{}[];':\")<>,.";
+ private static final String UNICODE_EXPECTED = "3 March März 三月 březen маршировать ";
+
+ @Test
+ void whenUsingCharClassRange_thenGetExceptedResult() {
+ String result = INPUT.replaceAll("[^\\sa-zA-Z0-9]", "");
+ assertEquals(EXPECTED, result);
+ }
+
+ @Test
+ void whenUsingPunctuationCharClass_thenGetExceptedResult() {
+ String result = INPUT.replaceAll("\\p{Punct}", "");
+ assertEquals(EXPECTED, result);
+ }
+
+ @Test
+ void whenInputContainsUnicodeChars_thenGetExceptedResult() {
+ String result1 = UNICODE_INPUT.replaceAll("[^\\sa-zA-Z0-9]", "");
+ assertNotEquals(UNICODE_EXPECTED, result1);
+
+ String actualResult1 = "3 March Mrz bezen ";
+ assertEquals(actualResult1, result1);
+
+
+ String result2 = UNICODE_INPUT.replaceAll("\\p{Punct}", "");
+ assertEquals(UNICODE_EXPECTED, result2);
+
+ String result3 = UNICODE_INPUT.replaceAll("[^\\s\\p{L}0-9]", "");
+ assertEquals(UNICODE_EXPECTED, result3);
+ }
+
+}
\ No newline at end of file
From 4a9e72664c9a8d94f7eb944b887ee62c36f57b4a Mon Sep 17 00:00:00 2001
From: Avin Buricha
Date: Sat, 6 May 2023 08:53:31 +0530
Subject: [PATCH 17/20] BAEL-6410 (#13919)
* BAEL-6410 | Article code
* Adding consumer code for article
---
.../kafka/headers/KafkaMessageHeaders.java | 88 +++++++++++++++
.../headers/KafkaMessageHeadersLiveTest.java | 104 ++++++++++++++++++
2 files changed, 192 insertions(+)
create mode 100644 apache-kafka-2/src/main/java/com/baeldung/kafka/headers/KafkaMessageHeaders.java
create mode 100644 apache-kafka-2/src/test/java/com/baeldung/kafka/headers/KafkaMessageHeadersLiveTest.java
diff --git a/apache-kafka-2/src/main/java/com/baeldung/kafka/headers/KafkaMessageHeaders.java b/apache-kafka-2/src/main/java/com/baeldung/kafka/headers/KafkaMessageHeaders.java
new file mode 100644
index 0000000000..2c8c14bfc5
--- /dev/null
+++ b/apache-kafka-2/src/main/java/com/baeldung/kafka/headers/KafkaMessageHeaders.java
@@ -0,0 +1,88 @@
+package com.baeldung.kafka.headers;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.common.header.Header;
+import org.apache.kafka.common.header.Headers;
+import org.apache.kafka.common.header.internals.RecordHeader;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KafkaMessageHeaders {
+
+ private static Logger logger = LoggerFactory.getLogger(KafkaMessageHeaders.class);
+
+ private static String TOPIC = "baeldung";
+ private static String MESSAGE_KEY = "message";
+ private static String MESSAGE_VALUE = "Hello World";
+ private static String HEADER_KEY = "website";
+ private static String HEADER_VALUE = "baeldung.com";
+
+ private static KafkaProducer producer;
+ private static KafkaConsumer consumer;
+
+ public static void main(String[] args) {
+ setup();
+
+ publishMessageWithCustomHeaders();
+
+ consumeMessageWithCustomHeaders();
+ }
+
+ private static void consumeMessageWithCustomHeaders() {
+ consumer.subscribe(Arrays.asList(TOPIC));
+
+ ConsumerRecords records = consumer.poll(Duration.ofMinutes(1));
+ for (ConsumerRecord record : records) {
+ logger.info(record.key());
+ logger.info(record.value());
+
+ Headers headers = record.headers();
+ for (Header header : headers) {
+ logger.info(header.key());
+ logger.info(new String(header.value()));
+ }
+ }
+ }
+
+ private static void publishMessageWithCustomHeaders() {
+ List headers = new ArrayList<>();
+ headers.add(new RecordHeader(HEADER_KEY, HEADER_VALUE.getBytes()));
+
+ ProducerRecord record1 = new ProducerRecord<>(TOPIC, null, MESSAGE_KEY, MESSAGE_VALUE, headers);
+ producer.send(record1);
+
+ ProducerRecord record2 = new ProducerRecord<>(TOPIC, null, System.currentTimeMillis(), MESSAGE_KEY, MESSAGE_VALUE, headers);
+ producer.send(record2);
+ }
+
+ private static void setup() {
+ Properties producerProperties = new Properties();
+ producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+ producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+
+ Properties consumerProperties = new Properties();
+ consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "ConsumerGroup1");
+
+ producer = new KafkaProducer<>(producerProperties);
+ consumer = new KafkaConsumer<>(consumerProperties);
+ }
+
+}
diff --git a/apache-kafka-2/src/test/java/com/baeldung/kafka/headers/KafkaMessageHeadersLiveTest.java b/apache-kafka-2/src/test/java/com/baeldung/kafka/headers/KafkaMessageHeadersLiveTest.java
new file mode 100644
index 0000000000..42cc572e07
--- /dev/null
+++ b/apache-kafka-2/src/test/java/com/baeldung/kafka/headers/KafkaMessageHeadersLiveTest.java
@@ -0,0 +1,104 @@
+package com.baeldung.kafka.headers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.clients.producer.RecordMetadata;
+import org.apache.kafka.common.header.Header;
+import org.apache.kafka.common.header.Headers;
+import org.apache.kafka.common.header.internals.RecordHeader;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.KafkaContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+// This live test needs a Docker Daemon running so that a kafka container can be created
+
+@Testcontainers
+public class KafkaMessageHeadersLiveTest {
+
+ private static String TOPIC = "baeldung";
+ private static String MESSAGE_KEY = "message";
+ private static String MESSAGE_VALUE = "Hello World";
+ private static String HEADER_KEY = "website";
+ private static String HEADER_VALUE = "baeldung.com";
+
+ private static KafkaProducer producer;
+ private static KafkaConsumer consumer;
+
+ @Container
+ private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
+
+ @BeforeAll
+ static void setup() {
+ KAFKA_CONTAINER.addExposedPort(9092);
+
+ Properties producerProperties = new Properties();
+ producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
+ producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+ producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+
+ Properties consumerProperties = new Properties();
+ consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
+ consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "ConsumerGroup1");
+
+ producer = new KafkaProducer<>(producerProperties);
+ consumer = new KafkaConsumer<>(consumerProperties);
+ }
+
+ @AfterAll
+ static void destroy() {
+ KAFKA_CONTAINER.stop();
+ }
+
+ @Test
+ void givenAMessageWithCustomHeaders_whenPublishedToKafkaAndConsumed_thenCheckForCustomHeaders() throws ExecutionException, InterruptedException {
+ List headers = new ArrayList<>();
+ headers.add(new RecordHeader(HEADER_KEY, HEADER_VALUE.getBytes()));
+
+ ProducerRecord record1 = new ProducerRecord<>(TOPIC, null, MESSAGE_KEY, MESSAGE_VALUE, headers);
+ Future future = producer.send(record1);
+
+ RecordMetadata metadata = future.get();
+
+ assertNotNull(metadata);
+
+ consumer.subscribe(Arrays.asList(TOPIC));
+
+ ConsumerRecords records = consumer.poll(Duration.ofMinutes(1));
+ for (ConsumerRecord record : records) {
+ assertEquals(MESSAGE_KEY, record.key());
+ assertEquals(MESSAGE_VALUE, record.value());
+
+ Headers consumedHeaders = record.headers();
+ assertNotNull(consumedHeaders);
+
+ for (Header header : consumedHeaders) {
+ assertEquals(HEADER_KEY, header.key());
+ assertEquals(HEADER_VALUE, new String(header.value()));
+ }
+ }
+ }
+}
From 7123ae8ad7f348ed47c750defbd7c1bd2de1e98d Mon Sep 17 00:00:00 2001
From: Ulisses Lima
Date: Sat, 6 May 2023 04:59:46 -0300
Subject: [PATCH 18/20] BAEL-6046 MongoDB - Field Level Encryption (#13859)
---
.../spring-boot-persistence-mongodb-3/pom.xml | 28 +++++-
.../boot/csfle/config/EncryptionConfig.java | 28 +++++-
.../boot/csfle/config/MongoClientConfig.java | 88 ++++++++++++++-----
.../boot/csfle/service/CitizenService.java | 33 ++++---
.../boot/csfle/web/CitizenController.java | 3 +-
.../boot/csfle/CitizenServiceLiveTest.java | 10 ++-
.../src/test/resources/embedded.properties | 6 +-
7 files changed, 150 insertions(+), 46 deletions(-)
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/pom.xml b/persistence-modules/spring-boot-persistence-mongodb-3/pom.xml
index b9a47aa703..484e0c0f7e 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/pom.xml
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/pom.xml
@@ -16,6 +16,21 @@
+
+ org.mongodb
+ mongodb-driver-sync
+ ${mongodb-driver.version}
+
+
+ org.mongodb
+ mongodb-driver-core
+ ${mongodb-driver.version}
+
+
+ org.mongodb
+ bson
+ ${mongodb-driver.version}
+
org.springframework.boot
spring-boot-starter-web
@@ -23,6 +38,16 @@
org.springframework.boot
spring-boot-starter-data-mongodb
+
+
+ org.mongodb
+ mongodb-driver-sync
+
+
+ org.mongodb
+ mongodb-driver-core
+
+
org.mongodb
@@ -37,7 +62,8 @@
- 1.6.1
+ 1.7.3
+ 4.9.1
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/EncryptionConfig.java b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/EncryptionConfig.java
index 0ff97eb6c1..1a74340057 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/EncryptionConfig.java
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/EncryptionConfig.java
@@ -1,5 +1,7 @@
package com.baeldung.boot.csfle.config;
+import java.io.File;
+
import org.bson.BsonBinary;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@@ -17,7 +19,13 @@ public class EncryptionConfig {
private String keyVaultAlias;
@Value("${com.baeldung.csfle.auto-decryption:false}")
- private Boolean autoDecryption;
+ private boolean autoDecryption;
+
+ @Value("${com.baeldung.csfle.auto-encryption:false}")
+ private boolean autoEncryption;
+
+ @Value("${com.baeldung.csfle.auto-encryption-lib:#{null}}")
+ private File autoEncryptionLib;
private BsonBinary dataKeyId;
@@ -41,7 +49,23 @@ public class EncryptionConfig {
return masterKeyPath;
}
- public Boolean getAutoDecryption() {
+ public boolean isAutoDecryption() {
return autoDecryption;
}
+
+ public boolean isAutoEncryption() {
+ return autoEncryption;
+ }
+
+ public File getAutoEncryptionLib() {
+ return autoEncryptionLib;
+ }
+
+ public String dataKeyIdUuid() {
+ if (dataKeyId == null)
+ throw new IllegalStateException("data key not initialized");
+
+ return dataKeyId.asUuid()
+ .toString();
+ }
}
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/MongoClientConfig.java b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/MongoClientConfig.java
index 0dff1ec86d..19d0af08b2 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/MongoClientConfig.java
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/config/MongoClientConfig.java
@@ -1,14 +1,15 @@
package com.baeldung.boot.csfle.config;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Map;
import org.bson.BsonBinary;
import org.bson.BsonDocument;
import org.bson.Document;
-import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@@ -51,14 +52,10 @@ public class MongoClientConfig extends AbstractMongoClientConfiguration {
@Bean
@Override
public MongoClient mongoClient() {
- MongoClient client;
try {
- client = MongoClients.create(clientSettings());
-
ClientEncryption encryption = clientEncryption();
- encryptionConfig.setDataKeyId(createOrRetrieveDataKey(client, encryption));
-
- return client;
+ encryptionConfig.setDataKeyId(createOrRetrieveDataKey(encryption));
+ return MongoClients.create(clientSettings());
} catch (IOException e) {
throw new IllegalStateException("unable to create client", e);
}
@@ -77,19 +74,10 @@ public class MongoClientConfig extends AbstractMongoClientConfiguration {
return ClientEncryptions.create(encryptionSettings);
}
- private BsonBinary createOrRetrieveDataKey(MongoClient client, ClientEncryption encryption) {
- MongoNamespace namespace = new MongoNamespace(encryptionConfig.getKeyVaultNamespace());
- MongoCollection keyVault = client.getDatabase(namespace.getDatabaseName())
- .getCollection(namespace.getCollectionName());
-
- Bson query = Filters.in("keyAltNames", encryptionConfig.getKeyVaultAlias());
- BsonDocument key = keyVault.withDocumentClass(BsonDocument.class)
- .find(query)
- .first();
-
+ private BsonBinary createOrRetrieveDataKey(ClientEncryption encryption) {
+ BsonDocument key = encryption.getKeyByAltName(encryptionConfig.getKeyVaultAlias());
if (key == null) {
- keyVault.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true)
- .partialFilterExpression(Filters.exists("keyAltNames")));
+ createKeyUniqueIndex();
DataKeyOptions options = new DataKeyOptions();
options.keyAltNames(Arrays.asList(encryptionConfig.getKeyVaultAlias()));
@@ -99,16 +87,68 @@ public class MongoClientConfig extends AbstractMongoClientConfiguration {
}
}
+ private void createKeyUniqueIndex() {
+ try (MongoClient client = MongoClients.create(MongoClientSettings.builder()
+ .applyConnectionString(new ConnectionString(uri))
+ .build())) {
+ MongoNamespace namespace = new MongoNamespace(encryptionConfig.getKeyVaultNamespace());
+ MongoCollection keyVault = client.getDatabase(namespace.getDatabaseName())
+ .getCollection(namespace.getCollectionName());
+
+ keyVault.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true)
+ .partialFilterExpression(Filters.exists("keyAltNames")));
+ }
+ }
+
private MongoClientSettings clientSettings() throws FileNotFoundException, IOException {
Builder settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(uri));
- if (encryptionConfig.getAutoDecryption()) {
- settings.autoEncryptionSettings(AutoEncryptionSettings.builder()
+ if (encryptionConfig.isAutoDecryption()) {
+ AutoEncryptionSettings.Builder builder = AutoEncryptionSettings.builder()
.keyVaultNamespace(encryptionConfig.getKeyVaultNamespace())
- .kmsProviders(LocalKmsUtils.providersMap(encryptionConfig.getMasterKeyPath()))
- .bypassAutoEncryption(true)
- .build());
+ .kmsProviders(LocalKmsUtils.providersMap(encryptionConfig.getMasterKeyPath()));
+
+ if (encryptionConfig.isAutoEncryption() && encryptionConfig.getDataKeyId() != null) {
+ File autoEncryptionLib = encryptionConfig.getAutoEncryptionLib();
+ if (!autoEncryptionLib.isFile()) {
+ throw new IllegalArgumentException("encryption lib must be an existing file");
+ }
+
+ Map map = new HashMap<>();
+ map.put("cryptSharedLibRequired", true);
+ map.put("cryptSharedLibPath", autoEncryptionLib.toString());
+ builder.extraOptions(map);
+
+ String keyUuid = encryptionConfig.dataKeyIdUuid();
+ HashMap schemaMap = new HashMap<>();
+ schemaMap.put(getDatabaseName() + ".citizens",
+ BsonDocument.parse("{"
+ + " bsonType: \"object\","
+ + " encryptMetadata: {"
+ + " keyId: [UUID(\"" + keyUuid + "\")]"
+ + " },"
+ + " properties: {"
+ + " email: {"
+ + " encrypt: {"
+ + " bsonType: \"string\","
+ + " algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\""
+ + " }"
+ + " },"
+ + " birthYear: {"
+ + " encrypt: {"
+ + " bsonType: \"int\","
+ + " algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Random\""
+ + " }"
+ + " }"
+ + " }"
+ + "}"));
+ builder.schemaMap(schemaMap);
+ } else {
+ builder.bypassAutoEncryption(true);
+ }
+
+ settings.autoEncryptionSettings(builder.build());
}
return settings.build();
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/service/CitizenService.java b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/service/CitizenService.java
index 6b3c463d0d..c93b00f3f8 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/service/CitizenService.java
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/service/CitizenService.java
@@ -35,16 +35,20 @@ public class CitizenService {
@Autowired
private ClientEncryption clientEncryption;
- public EncryptedCitizen save(Citizen citizen) {
- EncryptedCitizen encryptedCitizen = new EncryptedCitizen(citizen);
- encryptedCitizen.setEmail(encrypt(citizen.getEmail(), DETERMINISTIC_ALGORITHM));
- encryptedCitizen.setBirthYear(encrypt(citizen.getBirthYear(), RANDOM_ALGORITHM));
+ public Object save(Citizen citizen) {
+ if (encryptionConfig.isAutoEncryption()) {
+ return mongo.save(citizen);
+ } else {
+ EncryptedCitizen encryptedCitizen = new EncryptedCitizen(citizen);
+ encryptedCitizen.setEmail(encrypt(citizen.getEmail(), DETERMINISTIC_ALGORITHM));
+ encryptedCitizen.setBirthYear(encrypt(citizen.getBirthYear(), RANDOM_ALGORITHM));
- return mongo.save(encryptedCitizen);
+ return mongo.save(encryptedCitizen);
+ }
}
public List findAll() {
- if (!encryptionConfig.getAutoDecryption()) {
+ if (!encryptionConfig.isAutoDecryption()) {
List allEncrypted = mongo.findAll(EncryptedCitizen.class);
return allEncrypted.stream()
@@ -56,13 +60,20 @@ public class CitizenService {
}
public Citizen findByEmail(String email) {
- Query byEmail = new Query(Criteria.where("email")
- .is(encrypt(email, DETERMINISTIC_ALGORITHM)));
- if (!encryptionConfig.getAutoDecryption()) {
+ Criteria emailCriteria = Criteria.where("email");
+ if (encryptionConfig.isAutoEncryption()) {
+ emailCriteria.is(email);
+ } else {
+ emailCriteria
+ .is(encrypt(email, DETERMINISTIC_ALGORITHM));
+ }
+
+ Query byEmail = new Query(emailCriteria);
+ if (encryptionConfig.isAutoDecryption()) {
+ return mongo.findOne(byEmail, Citizen.class);
+ } else {
EncryptedCitizen encryptedCitizen = mongo.findOne(byEmail, EncryptedCitizen.class);
return decrypt(encryptedCitizen);
- } else {
- return mongo.findOne(byEmail, Citizen.class);
}
}
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/web/CitizenController.java b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/web/CitizenController.java
index d17435fb5e..7a2b2605cd 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/web/CitizenController.java
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/main/java/com/baeldung/boot/csfle/web/CitizenController.java
@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.boot.csfle.data.Citizen;
-import com.baeldung.boot.csfle.data.EncryptedCitizen;
import com.baeldung.boot.csfle.service.CitizenService;
@RestController
@@ -32,7 +31,7 @@ public class CitizenController {
}
@PostMapping
- public EncryptedCitizen post(@RequestBody Citizen citizen) {
+ public Object post(@RequestBody Citizen citizen) {
return service.save(citizen);
}
}
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/test/java/com/baeldung/boot/csfle/CitizenServiceLiveTest.java b/persistence-modules/spring-boot-persistence-mongodb-3/src/test/java/com/baeldung/boot/csfle/CitizenServiceLiveTest.java
index 471cb2883a..d57da43751 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/test/java/com/baeldung/boot/csfle/CitizenServiceLiveTest.java
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/test/java/com/baeldung/boot/csfle/CitizenServiceLiveTest.java
@@ -38,10 +38,14 @@ public class CitizenServiceLiveTest {
citizen.setName("Foo");
citizen.setEmail("foo@citizen.com");
- Binary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM);
+ Object saved = service.save(citizen);
+ if (saved instanceof EncryptedCitizen) {
+ Binary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM);
- EncryptedCitizen saved = service.save(citizen);
- assertEquals(encryptedEmail, saved.getEmail());
+ assertEquals(encryptedEmail, ((EncryptedCitizen) saved).getEmail());
+ } else {
+ assertEquals(citizen.getEmail(), ((Citizen) saved).getEmail());
+ }
}
@Test
diff --git a/persistence-modules/spring-boot-persistence-mongodb-3/src/test/resources/embedded.properties b/persistence-modules/spring-boot-persistence-mongodb-3/src/test/resources/embedded.properties
index 5325354e55..cd1c1d43c7 100644
--- a/persistence-modules/spring-boot-persistence-mongodb-3/src/test/resources/embedded.properties
+++ b/persistence-modules/spring-boot-persistence-mongodb-3/src/test/resources/embedded.properties
@@ -1,10 +1,10 @@
spring.mongodb.embedded.version=4.4.9
-spring.data.mongodb.uri=changeit
-spring.data.mongodb.database=changeit
+#spring.data.mongodb.uri=changeit
+#spring.data.mongodb.database=changeit
com.baeldung.csfle.kms-provider=local
com.baeldung.csfle.key-vault.namespace=encryption._keyVault
com.baeldung.csfle.key-vault.alias=master.key
-com.baeldung.csfle.master-key-path=/tmp/master.key
+#com.baeldung.csfle.master-key-path=/tmp/master.key
com.baeldung.csfle.auto-decryption=false
From ce79066afc6b20c1d2d9dbd09dc8cc34e096f300 Mon Sep 17 00:00:00 2001
From: Bhaskar Ghosh Dastidar
Date: Sat, 6 May 2023 21:58:20 +0530
Subject: [PATCH 19/20] [BAEL-6253] record equals hashcode (#13958)
* [BAEL-6253] records equals and hashcode
* [BAEL-6253] records equals and hashcode
* [BAEL-6253] records equals and hashcode test case
---------
Co-authored-by: Bhaskar
---
core-java-modules/core-java-records/pom.xml | 32 +++++++++++++++++++
.../baeldung/equalshashcoderecords/Movie.java | 26 +++++++++++++++
.../equalshashcoderecords/Person.java | 5 +++
.../CustomRecordEqualsHashCode.java | 30 +++++++++++++++++
core-java-modules/pom.xml | 1 +
5 files changed, 94 insertions(+)
create mode 100644 core-java-modules/core-java-records/pom.xml
create mode 100644 core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Movie.java
create mode 100644 core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Person.java
create mode 100644 core-java-modules/core-java-records/src/test/java/com/baeldung/equalshashcoderecords/CustomRecordEqualsHashCode.java
diff --git a/core-java-modules/core-java-records/pom.xml b/core-java-modules/core-java-records/pom.xml
new file mode 100644
index 0000000000..ed9a36fc14
--- /dev/null
+++ b/core-java-modules/core-java-records/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ core-java-modules
+ com.baeldung.core-java-modules
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ core-java-records
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 16
+ 16
+
+
+
+
+
+
+ 19
+ 19
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Movie.java b/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Movie.java
new file mode 100644
index 0000000000..e94638e8b5
--- /dev/null
+++ b/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Movie.java
@@ -0,0 +1,26 @@
+package com.baeldung.equalshashcoderecords;
+
+import java.util.Objects;
+
+record Movie(String name, Integer yearOfRelease, String distributor) {
+
+@Override
+public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other == null) {
+ return false;
+ }
+ Movie movie = (Movie) other;
+ if (movie.name.equals(this.name) && movie.yearOfRelease.equals(this.yearOfRelease)) {
+ return true;
+ }
+ return false;
+}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, yearOfRelease);
+ }
+}
diff --git a/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Person.java b/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Person.java
new file mode 100644
index 0000000000..7bfd8ae741
--- /dev/null
+++ b/core-java-modules/core-java-records/src/main/java/com/baeldung/equalshashcoderecords/Person.java
@@ -0,0 +1,5 @@
+package com.baeldung.equalshashcoderecords;
+
+public record Person(String firstName, String lastName, String SSN, String dateOfBirth) {
+};
+
diff --git a/core-java-modules/core-java-records/src/test/java/com/baeldung/equalshashcoderecords/CustomRecordEqualsHashCode.java b/core-java-modules/core-java-records/src/test/java/com/baeldung/equalshashcoderecords/CustomRecordEqualsHashCode.java
new file mode 100644
index 0000000000..074886304f
--- /dev/null
+++ b/core-java-modules/core-java-records/src/test/java/com/baeldung/equalshashcoderecords/CustomRecordEqualsHashCode.java
@@ -0,0 +1,30 @@
+package com.baeldung.equalshashcoderecords;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.Test;
+
+public class CustomRecordEqualsHashCode {
+ @Test
+ public void givenTwoRecords_whenDefaultEquals_thenCompareEquality() {
+ Person robert = new Person("Robert", "Frost", "HDHDB223", "2000-01-02");
+ Person mike = new Person("Mike", "Adams", "ABJDJ2883", "2001-01-02");
+ assertNotEquals(robert, mike);
+ }
+
+ @Test
+ public void givenTwoRecords_hashCodesShouldBeSame() {
+ Person robert = new Person("Robert", "Frost", "HDHDB223", "2000-01-02");
+ Person robertCopy = new Person("Robert", "Frost", "HDHDB223", "2000-01-02");
+ assertEquals(robert.hashCode(), robertCopy.hashCode());
+ }
+
+ @Test
+ public void givenTwoRecords_whenCustomImplementation_thenCompareEquality() {
+ Movie movie1 = new Movie("The Batman", 2022, "WB");
+ Movie movie2 = new Movie("The Batman", 2022, "Dreamworks");
+ assertEquals(movie1, movie2);
+ assertEquals(movie1.hashCode(), movie2.hashCode());
+ }
+}
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index 6f3aec8c3a..91f0dbfc28 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -141,6 +141,7 @@
core-java-uuid
pre-jpms
core-java-collections-maps-6
+ core-java-records
From 65cf74f42f5cbc2cb44c3865ec0ff251394f8436 Mon Sep 17 00:00:00 2001
From: Kai Yuan
Date: Sun, 7 May 2023 17:05:37 +0200
Subject: [PATCH 20/20] [compByteArrays] Comparing Two Byte Arrays in Java
(#13935)
---
.../compare/CompareByteArraysUnitTest.java | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/compare/CompareByteArraysUnitTest.java
diff --git a/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/compare/CompareByteArraysUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/compare/CompareByteArraysUnitTest.java
new file mode 100644
index 0000000000..4274acf83d
--- /dev/null
+++ b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/compare/CompareByteArraysUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.array.compare;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+public class CompareByteArraysUnitTest {
+ private final static String INPUT = "I am a magic string.";
+ private final static byte[] ARRAY1 = INPUT.getBytes();
+ private final static byte[] ARRAY2 = INPUT.getBytes();
+
+ @Test
+ void whenUsingEqualsSign_thenTwoArraysAreNotEqual() {
+ assertFalse(ARRAY1 == ARRAY2);
+ }
+
+ @Test
+ void whenUsingEquals_thenTwoArraysAreNotEqual() {
+ assertFalse(ARRAY1.equals(ARRAY2));
+ }
+
+ @Test
+ void whenUsingArrayEquals_thenTwoArraysAreEqual() {
+ assertTrue(Arrays.equals(ARRAY1, ARRAY2));
+ }
+
+ @Test
+ void whenComparingStringArrays_thenGetExpectedResult() {
+ String[] strArray1 = new String[] { "Java", "is", "great" };
+ String[] strArray2 = new String[] { "Java", "is", "great" };
+
+ assertFalse(strArray1 == strArray2);
+ assertFalse(strArray1.equals(strArray2));
+ assertTrue(Arrays.equals(strArray1, strArray2));
+ }
+}
\ No newline at end of file