From fabd8328a6c8e12dd0081fe082661cc6bf8bde51 Mon Sep 17 00:00:00 2001 From: h_sharifi Date: Tue, 13 Feb 2024 09:41:45 +0330 Subject: [PATCH 01/17] #BAEL-7484: add main source --- .../SpringMongoConnectionViaBuilderApp.java | 25 +++++ .../SpringMongoConnectionViaClientApp.java | 41 ++++++++ .../SpringMongoConnectionViaFactoryApp.java | 34 +++++++ ...SpringMongoConnectionViaPropertiesApp.java | 15 +++ .../application.properties | 5 + .../MongoConnectionApplicationLiveTest.java | 99 +++++++++++++++++++ 6 files changed, 219 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/builder/SpringMongoConnectionViaBuilderApp.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/client/SpringMongoConnectionViaClientApp.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/factory/SpringMongoConnectionViaFactoryApp.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/properties/SpringMongoConnectionViaPropertiesApp.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/main/resources/connection.via.properties/application.properties create mode 100644 persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/boot/connection/via/MongoConnectionApplicationLiveTest.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/builder/SpringMongoConnectionViaBuilderApp.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/builder/SpringMongoConnectionViaBuilderApp.java new file mode 100644 index 0000000000..3ef87fd27d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/builder/SpringMongoConnectionViaBuilderApp.java @@ -0,0 +1,25 @@ +package com.baeldung.boot.connection.via.builder; + +import com.mongodb.ConnectionString; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class SpringMongoConnectionViaBuilderApp { + + public static void main(String... args) { + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaBuilderApp.class); + app.web(WebApplicationType.NONE); + app.run(args); + } + + @Bean + public MongoClientSettingsBuilderCustomizer customizer(@Value("${custom.uri}") String uri) { + ConnectionString connection = new ConnectionString(uri); + return settings -> settings.applyConnectionString(connection); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/client/SpringMongoConnectionViaClientApp.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/client/SpringMongoConnectionViaClientApp.java new file mode 100644 index 0000000000..9993469a88 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/client/SpringMongoConnectionViaClientApp.java @@ -0,0 +1,41 @@ +package com.baeldung.boot.connection.via.client; + +import com.mongodb.client.ListDatabasesIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import org.bson.Document; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; + +@SpringBootApplication(exclude={EmbeddedMongoAutoConfiguration.class}) +public class SpringMongoConnectionViaClientApp extends AbstractMongoClientConfiguration { + + public static void main(String... args) { + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaClientApp.class); + app.web(WebApplicationType.NONE); + app.run(args); + } + + @Value("${spring.data.mongodb.uri}") + private String uri; + + @Value("${spring.data.mongodb.database}") + private String db; + + @Override + public MongoClient mongoClient() { + MongoClient client = MongoClients.create(uri); + ListDatabasesIterable databases = client.listDatabases(); + databases.forEach(System.out::println); + return client; + } + + @Override + protected String getDatabaseName() { + return db; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/factory/SpringMongoConnectionViaFactoryApp.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/factory/SpringMongoConnectionViaFactoryApp.java new file mode 100644 index 0000000000..7d04aa3792 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/factory/SpringMongoConnectionViaFactoryApp.java @@ -0,0 +1,34 @@ +package com.baeldung.boot.connection.via.factory; + +import com.mongodb.ConnectionString; +import com.mongodb.client.MongoClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.data.mongodb.core.MongoClientFactoryBean; + +@SpringBootApplication +public class SpringMongoConnectionViaFactoryApp { + + public static void main(String... args) { + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaFactoryApp.class); + app.web(WebApplicationType.NONE); + app.run(args); + } + + @Bean + public MongoClientFactoryBean mongo(@Value("${custom.uri}") String uri) throws Exception { + MongoClientFactoryBean mongo = new MongoClientFactoryBean(); + ConnectionString conn = new ConnectionString(uri); + mongo.setConnectionString(conn); + + mongo.setSingleton(false); + + MongoClient client = mongo.getObject(); + client.listDatabaseNames() + .forEach(System.out::println); + return mongo; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/properties/SpringMongoConnectionViaPropertiesApp.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/properties/SpringMongoConnectionViaPropertiesApp.java new file mode 100644 index 0000000000..b49149ee6f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/boot/connection/via/properties/SpringMongoConnectionViaPropertiesApp.java @@ -0,0 +1,15 @@ +package com.baeldung.boot.connection.via.properties; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; +import org.springframework.context.annotation.PropertySource; + +@PropertySource("classpath:connection.via.properties/application.properties") +@SpringBootApplication(exclude={EmbeddedMongoAutoConfiguration.class}) +public class SpringMongoConnectionViaPropertiesApp { + + public static void main(String... args) { + SpringApplication.run(SpringMongoConnectionViaPropertiesApp.class, args); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/connection.via.properties/application.properties b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/connection.via.properties/application.properties new file mode 100644 index 0000000000..e4161cd232 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/connection.via.properties/application.properties @@ -0,0 +1,5 @@ +spring.data.mongodb.host=localhost +spring.data.mongodb.port=27017 +spring.data.mongodb.database=baeldung +spring.data.mongodb.username=admin +spring.data.mongodb.password=password \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/boot/connection/via/MongoConnectionApplicationLiveTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/boot/connection/via/MongoConnectionApplicationLiveTest.java new file mode 100644 index 0000000000..59c509d9d4 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/boot/connection/via/MongoConnectionApplicationLiveTest.java @@ -0,0 +1,99 @@ +package com.baeldung.boot.connection.via; + +import com.baeldung.boot.connection.via.client.SpringMongoConnectionViaClientApp; +import com.baeldung.boot.connection.via.properties.SpringMongoConnectionViaPropertiesApp; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.bson.Document; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +public class MongoConnectionApplicationLiveTest { + private static final String HOST = "localhost"; + private static final String PORT = "27017"; + private static final String DB = "baeldung"; + private static final String USER = "admin"; + private static final String PASS = "password"; + + private void assertInsertSucceeds(ConfigurableApplicationContext context) { + String name = "A"; + + MongoTemplate mongo = context.getBean(MongoTemplate.class); + Document doc = Document.parse("{\"name\":\"" + name + "\"}"); + Document inserted = mongo.insert(doc, "items"); + + assertNotNull(inserted.get("_id")); + assertEquals(inserted.get("name"), name); + } + + @Test + public void whenPropertiesConfig_thenInsertSucceeds() { + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class); + app.run(); + + assertInsertSucceeds(app.context()); + } + + @Test + public void givenPrecedence_whenSystemConfig_thenInsertSucceeds() { + System.setProperty("spring.data.mongodb.host", HOST); + System.setProperty("spring.data.mongodb.port", PORT); + System.setProperty("spring.data.mongodb.database", DB); + System.setProperty("spring.data.mongodb.username", USER); + System.setProperty("spring.data.mongodb.password", PASS); + + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class) + .properties( + "spring.data.mongodb.host=oldValue", + "spring.data.mongodb.port=oldValue", + "spring.data.mongodb.database=oldValue", + "spring.data.mongodb.username=oldValue", + "spring.data.mongodb.password=oldValue" + ); + app.run(); + + assertInsertSucceeds(app.context()); + } + + @Test + public void givenConnectionUri_whenAlsoIncludingIndividualParameters_thenInvalidConfig() { + System.setProperty( + "spring.data.mongodb.uri", + "mongodb://" + USER + ":" + PASS + "@" + HOST + ":" + PORT + "/" + DB + ); + + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class) + .properties( + "spring.data.mongodb.host=" + HOST, + "spring.data.mongodb.port=" + PORT, + "spring.data.mongodb.username=" + USER, + "spring.data.mongodb.password=" + PASS + ); + + BeanCreationException e = assertThrows(BeanCreationException.class, () -> { + app.run(); + }); + + Throwable rootCause = e.getRootCause(); + assertTrue(rootCause instanceof IllegalStateException); + assertThat(rootCause.getMessage() + .contains("Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified")); + } + + @Test + public void whenClientConfig_thenInsertSucceeds() { + SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaClientApp.class); + app.web(WebApplicationType.NONE) + .run( + "--spring.data.mongodb.uri=mongodb://" + USER + ":" + PASS + "@" + HOST + ":" + PORT + "/" + DB, + "--spring.data.mongodb.database=" + DB + ); + + assertInsertSucceeds(app.context()); + } +} \ No newline at end of file From ce26271629df5d36bb2fb352233bf4cdb135f4de Mon Sep 17 00:00:00 2001 From: Sam Gardner Date: Tue, 13 Feb 2024 14:27:10 +0000 Subject: [PATCH 02/17] BAEL-7522 Add code for Java 18 simple web server --- .../baeldung/simple_web_server/WebServer.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java new file mode 100644 index 0000000000..db36477fdb --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java @@ -0,0 +1,59 @@ +package com.baeldung.simple_web_server; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.function.Predicate; + +import com.sun.net.httpserver.Filter; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpHandlers; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.Request; +import com.sun.net.httpserver.SimpleFileServer; + +public class WebServer { + + private final InetSocketAddress address = new InetSocketAddress(8080); + private final Path path = Path.of("/"); + + public static void main(String[] args) { + WebServer webServer = new WebServer(); + HttpServer server = webServer.createWithHandler_401Response(); + server.start(); + } + + private HttpServer createBasic() { + return SimpleFileServer.createFileServer(address, path, SimpleFileServer.OutputLevel.VERBOSE); + } + + private HttpServer createWithHandler() throws IOException { + HttpServer server = SimpleFileServer.createFileServer(address, path, SimpleFileServer.OutputLevel.VERBOSE); + HttpHandler handler = SimpleFileServer.createFileHandler(Path.of("/Users")); + server.createContext("/test", handler); + return server; + } + + private HttpServer createWithHandler_401Response() { + Predicate findAllowedPath = r -> r.getRequestURI() + .getPath() + .equals("/test/allowed"); + + HttpHandler allowedResponse = HttpHandlers.of(200, Headers.of("Allow", "GET"), "Welcome"); + HttpHandler deniedResponse = HttpHandlers.of(401, Headers.of("Deny", "GET"), "Denied"); + + HttpHandler handler = HttpHandlers.handleOrElse(findAllowedPath, allowedResponse, deniedResponse); + + HttpServer server = SimpleFileServer.createFileServer(address, path, SimpleFileServer.OutputLevel.VERBOSE); + server.createContext("/test", handler); + return server; + } + + private HttpServer createWithFilter() throws IOException { + Filter filter = SimpleFileServer.createOutputFilter(System.out, SimpleFileServer.OutputLevel.INFO); + HttpHandler handler = SimpleFileServer.createFileHandler(Path.of("/Users")); + return HttpServer.create(new InetSocketAddress(8080), 10, "/test", handler, filter); + } + +} From 972571e258ac01d2466320ea036e3ac99b978411 Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sun, 18 Feb 2024 07:48:29 +0800 Subject: [PATCH 03/17] [string-in-mirror] string - mirror reflection --- ...kStringEqualsMirrorReflectionUnitTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java diff --git a/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java b/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java new file mode 100644 index 0000000000..16360aff39 --- /dev/null +++ b/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.string.chkstringinmirror; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +public class CheckStringEqualsMirrorReflectionUnitTest { + + private final static Set SYMMETRIC_LETTERS = Set.of('A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y'); + + boolean isReflectionEqual(String input) { + return containsOnlySymmetricLetters(input) && isPalindrome(input); + } + + private boolean containsOnlySymmetricLetters(String input) { + Set characterSet = input.chars() + .mapToObj(c -> (char) c) + .collect(Collectors.toSet()); + characterSet.removeAll(SYMMETRIC_LETTERS); + return characterSet.isEmpty(); + } + + private boolean isPalindrome(String input) { + String reversed = new StringBuilder(input).reverse() + .toString(); + return input.equals(reversed); + } + + @Test + void whenCallingIsReflectionEqual_thenGetExpectedResults() { + assertFalse(isReflectionEqual("LOL")); + assertFalse(isReflectionEqual("AXY")); + assertFalse(isReflectionEqual("HUHU")); + + assertTrue(isReflectionEqual("")); + assertTrue(isReflectionEqual("AAA")); + assertTrue(isReflectionEqual("HUH")); + assertTrue(isReflectionEqual("HIMMIH")); + assertTrue(isReflectionEqual("HIMIH")); + } + +} \ No newline at end of file From b8c241574575b33294df3f6129be08c32531d8f4 Mon Sep 17 00:00:00 2001 From: Sam Gardner Date: Mon, 19 Feb 2024 13:16:43 +0000 Subject: [PATCH 04/17] BAEL-7522-Rename-package-for-simple-web-server --- .../{simple_web_server => simplewebserver}/WebServer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename core-java-modules/core-java-18/src/main/java/com/baeldung/{simple_web_server => simplewebserver}/WebServer.java (92%) diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/simplewebserver/WebServer.java similarity index 92% rename from core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java rename to core-java-modules/core-java-18/src/main/java/com/baeldung/simplewebserver/WebServer.java index db36477fdb..ba1747b379 100644 --- a/core-java-modules/core-java-18/src/main/java/com/baeldung/simple_web_server/WebServer.java +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/simplewebserver/WebServer.java @@ -1,4 +1,4 @@ -package com.baeldung.simple_web_server; +package com.baeldung.simplewebserver; import java.io.IOException; import java.net.InetSocketAddress; @@ -20,7 +20,7 @@ public class WebServer { public static void main(String[] args) { WebServer webServer = new WebServer(); - HttpServer server = webServer.createWithHandler_401Response(); + HttpServer server = webServer.createWithHandler401Response(); server.start(); } @@ -35,7 +35,7 @@ public class WebServer { return server; } - private HttpServer createWithHandler_401Response() { + private HttpServer createWithHandler401Response() { Predicate findAllowedPath = r -> r.getRequestURI() .getPath() .equals("/test/allowed"); From 9d13085bbc7e11a4c8ad76a21a090e915ea24b0f Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Tue, 20 Feb 2024 07:30:30 +0800 Subject: [PATCH 05/17] [string-in-mirror] renaming etc. --- ...kStringEqualsMirrorReflectionUnitTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java b/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java index 16360aff39..69329bf37c 100644 --- a/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java +++ b/core-java-modules/core-java-string-algorithms-4/src/test/java/com/baeldung/string/chkstringinmirror/CheckStringEqualsMirrorReflectionUnitTest.java @@ -12,7 +12,21 @@ public class CheckStringEqualsMirrorReflectionUnitTest { private final static Set SYMMETRIC_LETTERS = Set.of('A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y'); - boolean isReflectionEqual(String input) { + @Test + void whenCallingIsReflectionEqual_thenGetExpectedResults() { + assertFalse(isMirrorImageEqual("LOL")); + assertFalse(isMirrorImageEqual("AXY")); + assertFalse(isMirrorImageEqual("HUHU")); + + assertTrue(isMirrorImageEqual("")); + assertTrue(isMirrorImageEqual("AAA")); + assertTrue(isMirrorImageEqual("HUH")); + assertTrue(isMirrorImageEqual("HIMMIH")); + assertTrue(isMirrorImageEqual("HIMIH")); + } + + + public boolean isMirrorImageEqual(String input) { return containsOnlySymmetricLetters(input) && isPalindrome(input); } @@ -30,17 +44,4 @@ public class CheckStringEqualsMirrorReflectionUnitTest { return input.equals(reversed); } - @Test - void whenCallingIsReflectionEqual_thenGetExpectedResults() { - assertFalse(isReflectionEqual("LOL")); - assertFalse(isReflectionEqual("AXY")); - assertFalse(isReflectionEqual("HUHU")); - - assertTrue(isReflectionEqual("")); - assertTrue(isReflectionEqual("AAA")); - assertTrue(isReflectionEqual("HUH")); - assertTrue(isReflectionEqual("HIMMIH")); - assertTrue(isReflectionEqual("HIMIH")); - } - } \ No newline at end of file From bd36eddecaa79e19316fd270790822eec7de7731 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Tue, 20 Feb 2024 01:19:05 +0100 Subject: [PATCH 06/17] JAVA-29315: Upgrade spring-security-web-react to parent-spring-6 (#15920) --- .../spring-security-web-react/pom.xml | 27 ++++++------- .../com/baeldung/spring/RestController.java | 3 +- .../baeldung/spring/SecSecurityConfig.java | 39 ++++++++----------- .../java/com/baeldung/SpringContextTest.java | 19 +++++---- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/spring-security-modules/spring-security-web-react/pom.xml b/spring-security-modules/spring-security-web-react/pom.xml index 3a519acf09..f8f98ced23 100644 --- a/spring-security-modules/spring-security-web-react/pom.xml +++ b/spring-security-modules/spring-security-web-react/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-spring-5 + parent-spring-6 0.0.1-SNAPSHOT - ../../parent-spring-5 + ../../parent-spring-6 @@ -20,17 +20,17 @@ org.springframework.security spring-security-web - ${spring-security.version} + ${spring.version} org.springframework.security spring-security-config - ${spring-security.version} + ${spring.version} org.springframework.security spring-security-taglibs - ${spring-security.version} + ${spring.version} @@ -65,22 +65,21 @@ - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} + jakarta.servlet + jakarta.servlet-api + ${jakarta-servlet-api.version} provided - javax.servlet - jstl - ${jstl.version} - runtime + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + ${jakarta-servlet-jsp.version} org.springframework.boot spring-boot-starter-test - ${spring-boot-starter-test.version} + ${spring-boot.version} test @@ -153,6 +152,8 @@ v8.11.3 6.1.0 + 3.0.0 + 6.1.0-M1 \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java index 4084df9698..07e2b9c2ea 100644 --- a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java +++ b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/RestController.java @@ -1,5 +1,4 @@ package com.baeldung.spring; -import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,6 +9,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import jakarta.servlet.http.HttpServletRequest; + @Controller @RequestMapping("/rest") public class RestController { diff --git a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java index 7e588f4d97..67c0c181ca 100644 --- a/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-modules/spring-security-web-react/src/main/java/com/baeldung/spring/SecSecurityConfig.java @@ -38,28 +38,21 @@ public class SecSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf() - .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) - .and() - .authorizeRequests() - .antMatchers("/admin/**") - .hasRole("ADMIN") - .antMatchers("/anonymous*") - .anonymous() - .antMatchers(HttpMethod.GET, "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/rest") - .permitAll() - .anyRequest() - .authenticated() - .and() - .formLogin() - .loginPage("/index.html") - .loginProcessingUrl("/perform_login") - .defaultSuccessUrl("/homepage.html", true) - .failureUrl("/index.html?error=true") - .and() - .logout() - .logoutUrl("/perform_logout") - .deleteCookies("JSESSIONID"); - return http.build(); + return http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())) + .authorizeHttpRequests(request -> request.requestMatchers("/admin/**") + .hasRole("ADMIN") + .requestMatchers("/anonymous*") + .anonymous() + .requestMatchers(HttpMethod.GET, "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/rest") + .permitAll() + .anyRequest() + .authenticated()) + .formLogin(form -> form.loginPage("/index.html") + .loginProcessingUrl("/perform_login") + .defaultSuccessUrl("/homepage.html", true) + .failureUrl("/index.html?error=true")) + .logout(logout -> logout.logoutUrl("/perform_logout") + .deleteCookies("JSESSIONID")) + .build(); } } diff --git a/spring-security-modules/spring-security-web-react/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-security-web-react/src/test/java/com/baeldung/SpringContextTest.java index 43ddb515eb..fcb1764aa0 100644 --- a/spring-security-modules/spring-security-web-react/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-security-modules/spring-security-web-react/src/test/java/com/baeldung/SpringContextTest.java @@ -1,19 +1,22 @@ package com.baeldung; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.web.WebAppConfiguration; + import com.baeldung.spring.MvcConfig; import com.baeldung.spring.SecSecurityConfig; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = { MvcConfig.class, SecSecurityConfig.class }) -public class SpringContextTest { +@ExtendWith(SpringExtension.class) +class SpringContextTest { @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { + void whenSpringContextIsBootstrapped_thenNoExceptions() { } } + + From d4f8b4ff660b894f92369d53157c5e4213f7e1ce Mon Sep 17 00:00:00 2001 From: Diegom203 <153622681+Diegom203@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:24:35 -0800 Subject: [PATCH 07/17] baeldung-articles : BAEL-5937 (#15922) Create JavaType From Class with Jackson (commit). --- .../JavaTypeFromClassUnitTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 jackson-modules/jackson-custom-conversions/javatypefromclassinjava/JavaTypeFromClassUnitTest.java diff --git a/jackson-modules/jackson-custom-conversions/javatypefromclassinjava/JavaTypeFromClassUnitTest.java b/jackson-modules/jackson-custom-conversions/javatypefromclassinjava/JavaTypeFromClassUnitTest.java new file mode 100644 index 0000000000..bb95d9987b --- /dev/null +++ b/jackson-modules/jackson-custom-conversions/javatypefromclassinjava/JavaTypeFromClassUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.javatypefromclassinjava; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +public class JavaTypeFromClassUnitTest { + + @Test + public void givenGenericClass_whenCreatingJavaType_thenJavaTypeNotNull() { + Class myClass = MyGenericClass.class; + + JavaType javaType = TypeFactory.defaultInstance().constructType(myClass); + + assertNotNull(javaType); + } + + @Test + public void givenParametricType_whenCreatingJavaType_thenJavaTypeNotNull() { + Class containerClass = Container.class; + Class elementType = String.class; + + JavaType javaType = TypeFactory.defaultInstance().constructParametricType(containerClass, elementType); + + assertNotNull(javaType); + } + + static class MyGenericClass { + // Class implementation + } + + static class Container { + // Class implementation + } + +} From abb1f462b9d3ddddab54eba7fc6c1684f26e6b21 Mon Sep 17 00:00:00 2001 From: Wynn Teo <49014791+wynnteo@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:11:25 +0800 Subject: [PATCH 08/17] Bael 7541 (#15877) * BAEL-7490 read write file in separate thread * Change the to try resources * Update the code to sync with article * BAEL-7541 compare runAsync and supplyAsync --- .../runvssupply/RunAndSupplyCompare.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/runvssupply/RunAndSupplyCompare.java diff --git a/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/runvssupply/RunAndSupplyCompare.java b/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/runvssupply/RunAndSupplyCompare.java new file mode 100644 index 0000000000..a3b80d2db2 --- /dev/null +++ b/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/runvssupply/RunAndSupplyCompare.java @@ -0,0 +1,79 @@ +package com.baeldung.runvssupply; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class RunAndSupplyCompare { + + public static void main(String args[]) throws ExecutionException, InterruptedException { + chainingOperationCompare(); + } + + public static void inputAndReturnCompare() throws ExecutionException, InterruptedException { + CompletableFuture runAsyncFuture = CompletableFuture.runAsync(() -> { + // Perform non-result producing task + System.out.println("Task executed asynchronously"); + }); + + CompletableFuture supplyAsyncFuture = CompletableFuture.supplyAsync(() -> { + // Perform result-producing task + return "Result of the asynchronous computation"; + }); + // Get the result later + String result = supplyAsyncFuture.get(); + System.out.println("Result: " + result); + } + + public static void exceptionHandlingCompare() { + CompletableFuture runAsyncFuture = CompletableFuture.runAsync(() -> { + // Task that may throw an exception + throw new RuntimeException("Exception occurred in asynchronous task"); + }); + try { + runAsyncFuture.get(); + // Exception will be thrown here + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + System.out.println("Exception caught: " + cause.getMessage()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + CompletableFuture supplyAsyncFuture = CompletableFuture.supplyAsync(() -> { + // Task that may throw an exception + throw new RuntimeException("Exception occurred in asynchronous task"); + }) + .exceptionally(ex -> { + // Exception handling logic + return "Default value"; + }); + + Object result = supplyAsyncFuture.join(); + // Get the result or default value + System.out.println("Result: " + result); + } + + public static void chainingOperationCompare() { + CompletableFuture runAsyncFuture = CompletableFuture.runAsync(() -> { + // Perform non-result producing task + System.out.println("Task executed asynchronously"); + }); + runAsyncFuture.thenRun(() -> { + // Execute another task after the completion of runAsync() + System.out.println("Another task executed after runAsync() completes"); + }); + + CompletableFuture supplyAsyncFuture = CompletableFuture.supplyAsync(() -> { + // Perform result-producing task + return "Result of the asynchronous computation"; + }); + supplyAsyncFuture.thenApply(result -> { + // Transform the result + return result.toUpperCase(); + }) + .thenAccept(transformedResult -> { + // Consume the transformed result + System.out.println("Transformed Result: " + transformedResult); + }); + } +} From 536ffe9106ad7baf9f20b4bf572fc7d9e75dc5e0 Mon Sep 17 00:00:00 2001 From: vaibhav007jain <72961247+vaibhav007jain@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:34:26 +0530 Subject: [PATCH 09/17] Bael-7439-intro-to-etcd (#15892) * Update pom.xml * Create JetcdExample.java --- libraries-data-io/pom.xml | 9 +++++- .../java/com/baeldung/etcd/JetcdExample.java | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 libraries-data-io/src/main/java/com/baeldung/etcd/JetcdExample.java diff --git a/libraries-data-io/pom.xml b/libraries-data-io/pom.xml index 9fc2814312..0101f724f0 100644 --- a/libraries-data-io/pom.xml +++ b/libraries-data-io/pom.xml @@ -95,6 +95,12 @@ protobuf-java ${google-protobuf.version} + + + io.etcd + jetcd-core + ${jetcd-version} + @@ -110,6 +116,7 @@ 1.15 0.14.2 3.17.3 + 0.7.7 - \ No newline at end of file + diff --git a/libraries-data-io/src/main/java/com/baeldung/etcd/JetcdExample.java b/libraries-data-io/src/main/java/com/baeldung/etcd/JetcdExample.java new file mode 100644 index 0000000000..4174143d8a --- /dev/null +++ b/libraries-data-io/src/main/java/com/baeldung/etcd/JetcdExample.java @@ -0,0 +1,32 @@ +package com.baeldung.etcd; + +import java.util.concurrent.CompletableFuture; + +import io.etcd.jetcd.kv.GetResponse; +import io.etcd.jetcd.ByteSequence; +import io.etcd.jetcd.KV; +import io.etcd.jetcd.Client; + +public class JetcdExample { + public static void main(String[] args) { + String etcdEndpoint = "http://localhost:2379"; + ByteSequence key = ByteSequence.from("/mykey".getBytes()); + ByteSequence value = ByteSequence.from("Hello, etcd!".getBytes()); + + try (Client client = Client.builder().endpoints(etcdEndpoint).build()) { + KV kvClient = client.getKVClient(); + + // Put a key-value pair + kvClient.put(key, value).get(); + + // Retrieve the value using CompletableFuture + CompletableFuture getFuture = kvClient.get(key); + GetResponse response = getFuture.get(); + + // Delete the key + kvClient.delete(key).get(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} From b4107947fc382253c1efbf55d5b95070d201170d Mon Sep 17 00:00:00 2001 From: Ana Peterlic Date: Tue, 20 Feb 2024 08:31:33 +0100 Subject: [PATCH 10/17] Update index.html --- .../src/main/resources/templates/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-boot-modules/spring-boot-artifacts/src/main/resources/templates/index.html b/spring-boot-modules/spring-boot-artifacts/src/main/resources/templates/index.html index c1314558f6..f41373d093 100644 --- a/spring-boot-modules/spring-boot-artifacts/src/main/resources/templates/index.html +++ b/spring-boot-modules/spring-boot-artifacts/src/main/resources/templates/index.html @@ -1,7 +1,7 @@ WebJars Demo - +

Welcome Home

@@ -12,8 +12,8 @@ - - + + From a4b26ac450a62fd21cd63b63b02f5146d4cad246 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Tue, 20 Feb 2024 17:01:36 +0530 Subject: [PATCH 11/17] JAVA-31205 Fix parent pom names for spring-cloud-eureka (#15911) --- .../spring-cloud-eureka-client-profiles/pom.xml | 2 +- .../spring-cloud-eureka/spring-cloud-eureka-client/pom.xml | 2 +- .../spring-cloud-eureka-feign-client-integration-test/pom.xml | 2 +- .../spring-cloud-eureka-feign-client/pom.xml | 2 +- .../spring-cloud-eureka/spring-cloud-eureka-server/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client-profiles/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client-profiles/pom.xml index 23e06a55f9..283cfcf7bb 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client-profiles/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client-profiles/pom.xml @@ -10,7 +10,7 @@ Spring Cloud Eureka Sample Client - com.baeldung.spring.cloud + com.baeldung spring-cloud-eureka 1.0.0-SNAPSHOT diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml index a16059a19b..2b7a8d0a69 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml @@ -10,7 +10,7 @@ Spring Cloud Eureka Sample Client - com.baeldung.spring.cloud + com.baeldung spring-cloud-eureka 1.0.0-SNAPSHOT diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml index 1ed514d146..f8b8a32719 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml @@ -10,7 +10,7 @@ Spring Cloud Eureka - Feign Client Integration Tests - com.baeldung.spring.cloud + com.baeldung spring-cloud-eureka 1.0.0-SNAPSHOT diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml index ca29a890dd..6c3b25f878 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml @@ -10,7 +10,7 @@ Spring Cloud Eureka - Sample Feign Client - com.baeldung.spring.cloud + com.baeldung spring-cloud-eureka 1.0.0-SNAPSHOT diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml index 7ba300289e..f3e5a78be3 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml @@ -10,7 +10,7 @@ Spring Cloud Eureka Server Demo - com.baeldung.spring.cloud + com.baeldung spring-cloud-eureka 1.0.0-SNAPSHOT From c77c0deea5d8e5a9f22dee5a55a3c1b9c7fc61be Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Tue, 20 Feb 2024 13:34:36 +0200 Subject: [PATCH 12/17] [JAVA-31203] Upgraded spring-cloud-config to spring boot 3 (#15861) --- spring-cloud-modules/spring-cloud-config/pom.xml | 9 +++++---- .../config/server/SecurityConfiguration.java | 15 ++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/spring-cloud-modules/spring-cloud-config/pom.xml b/spring-cloud-modules/spring-cloud-config/pom.xml index c256e82d1b..1c5b16916e 100644 --- a/spring-cloud-modules/spring-cloud-config/pom.xml +++ b/spring-cloud-modules/spring-cloud-config/pom.xml @@ -10,9 +10,10 @@ pom - com.baeldung.spring.cloud - spring-cloud-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -35,7 +36,7 @@ - 2021.0.3 + 2022.0.3 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-config/spring-cloud-config-server/src/main/java/com/baeldung/spring/cloud/config/server/SecurityConfiguration.java b/spring-cloud-modules/spring-cloud-config/spring-cloud-config-server/src/main/java/com/baeldung/spring/cloud/config/server/SecurityConfiguration.java index 428a8f23c6..ebe9205a45 100644 --- a/spring-cloud-modules/spring-cloud-config/spring-cloud-config-server/src/main/java/com/baeldung/spring/cloud/config/server/SecurityConfiguration.java +++ b/spring-cloud-modules/spring-cloud-config/spring-cloud-config-server/src/main/java/com/baeldung/spring/cloud/config/server/SecurityConfiguration.java @@ -2,6 +2,7 @@ package com.baeldung.spring.cloud.config.server; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @@ -10,13 +11,13 @@ public class SecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf() - .ignoringAntMatchers("/encrypt/**") - .ignoringAntMatchers("/decrypt/**"); - http.authorizeRequests((requests) -> requests.anyRequest() - .authenticated()); - http.formLogin(); - http.httpBasic(); + http.csrf(csrf -> csrf.ignoringRequestMatchers( + "/encrypt/**", "/decrypt/**" + )) + .authorizeRequests(authz -> authz.anyRequest().authenticated()) + .formLogin(Customizer.withDefaults()) + .httpBasic(Customizer.withDefaults()); + return http.build(); } } From acb28bdec3102f39cb94133d2740cef81df19580 Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Tue, 20 Feb 2024 19:58:46 +0530 Subject: [PATCH 13/17] JAVA-31341 Fix spring-jooq and spring-mybatis module (#15897) --- persistence-modules/spring-jooq/pom.xml | 2 +- persistence-modules/spring-mybatis/pom.xml | 9 --------- spring-boot-modules/spring-boot-properties/pom.xml | 10 ++++++++-- spring-boot-modules/spring-boot-ssl-bundles/pom.xml | 1 - .../SecureRestTemplateConfig.java | 2 +- .../springbootsslbundles/SecureServiceRestApi.java | 3 ++- spring-jinq/pom.xml | 2 -- .../spring-reactive-exceptions/pom.xml | 11 +++++++---- spring-web-modules/spring-rest-http/pom.xml | 7 +++++++ 9 files changed, 26 insertions(+), 21 deletions(-) diff --git a/persistence-modules/spring-jooq/pom.xml b/persistence-modules/spring-jooq/pom.xml index 1387635afe..230397da9d 100644 --- a/persistence-modules/spring-jooq/pom.xml +++ b/persistence-modules/spring-jooq/pom.xml @@ -194,7 +194,7 @@ 1.0.0 1.5 1.0.0 - 3.1.5 + 2.2.224 \ No newline at end of file diff --git a/persistence-modules/spring-mybatis/pom.xml b/persistence-modules/spring-mybatis/pom.xml index d179881710..f164f4b6f9 100644 --- a/persistence-modules/spring-mybatis/pom.xml +++ b/persistence-modules/spring-mybatis/pom.xml @@ -19,12 +19,10 @@ org.springframework spring-context - ${org.springframework.version} org.springframework spring-beans - ${org.springframework.version} @@ -36,12 +34,10 @@ com.h2database h2 - ${h2.version} org.springframework spring-jdbc - ${org.springframework.version} org.mybatis @@ -61,7 +57,6 @@ org.springframework spring-test - ${org.springframework.version} test @@ -77,14 +72,10 @@ - - 6.0.13 - 3.0.3 3.5.2 3.0.3 true - 3.1.5 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml index 7614941f2d..fa3fc954b3 100644 --- a/spring-boot-modules/spring-boot-properties/pom.xml +++ b/spring-boot-modules/spring-boot-properties/pom.xml @@ -104,6 +104,13 @@ false + + org.apache.maven.plugins + maven-compiler-plugin + + true + + @@ -142,12 +149,11 @@ - 2022.0.4 + 2023.0.0 1.10 @ com.baeldung.yaml.MyApplication - 3.1.5 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-ssl-bundles/pom.xml b/spring-boot-modules/spring-boot-ssl-bundles/pom.xml index 8edbd9c79e..1f4e58f21f 100644 --- a/spring-boot-modules/spring-boot-ssl-bundles/pom.xml +++ b/spring-boot-modules/spring-boot-ssl-bundles/pom.xml @@ -53,7 +53,6 @@ 5.0.3 - 3.1.5 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureRestTemplateConfig.java b/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureRestTemplateConfig.java index 48eda219dd..cae3b24d8c 100644 --- a/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureRestTemplateConfig.java +++ b/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureRestTemplateConfig.java @@ -27,7 +27,7 @@ public class SecureRestTemplateConfig { this.sslContext = sslBundle.createSslContext(); } - @Bean + @Bean(name="secureRestTemplate") public RestTemplate secureRestTemplate() { final SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create().setSslContext(this.sslContext).build(); final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslSocketFactory).build(); diff --git a/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureServiceRestApi.java b/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureServiceRestApi.java index 3ed919b957..d7b87c4c5a 100644 --- a/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureServiceRestApi.java +++ b/spring-boot-modules/spring-boot-ssl-bundles/src/main/java/com/baeldung/springbootsslbundles/SecureServiceRestApi.java @@ -1,6 +1,7 @@ package com.baeldung.springbootsslbundles; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -11,7 +12,7 @@ public class SecureServiceRestApi { private final RestTemplate restTemplate; @Autowired - public SecureServiceRestApi(RestTemplate restTemplate) { + public SecureServiceRestApi(@Qualifier("secureRestTemplate") RestTemplate restTemplate) { this.restTemplate = restTemplate; } diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml index 4ba2028bc6..4695950153 100644 --- a/spring-jinq/pom.xml +++ b/spring-jinq/pom.xml @@ -38,7 +38,6 @@ org.hibernate.orm hibernate-core - ${hibernate-core.version} @@ -65,7 +64,6 @@ 2.0.1 6.4.2.Final - 3.1.5 \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-exceptions/pom.xml b/spring-reactive-modules/spring-reactive-exceptions/pom.xml index e9208c8b20..1f24f9cd1c 100644 --- a/spring-reactive-modules/spring-reactive-exceptions/pom.xml +++ b/spring-reactive-modules/spring-reactive-exceptions/pom.xml @@ -51,11 +51,14 @@ JAR + + org.apache.maven.plugins + maven-compiler-plugin + + true + + - - 3.1.5 - - diff --git a/spring-web-modules/spring-rest-http/pom.xml b/spring-web-modules/spring-rest-http/pom.xml index 8d3ea82c44..f93e4274e9 100644 --- a/spring-web-modules/spring-rest-http/pom.xml +++ b/spring-web-modules/spring-rest-http/pom.xml @@ -71,6 +71,13 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + true + + From 6328bf349e9a3e47a615bc466028d56516df466f Mon Sep 17 00:00:00 2001 From: Constantin <50400363+constantinurs@users.noreply.github.com> Date: Wed, 21 Feb 2024 00:14:38 +0200 Subject: [PATCH 14/17] [BAEL-7199] Override bootstrap servers property (#15708) --- spring-kafka-2/src/main/resources/application.properties | 2 +- .../com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java | 3 ++- .../multipletopics/KafkaMultipleTopicsIntegrationTest.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-kafka-2/src/main/resources/application.properties b/spring-kafka-2/src/main/resources/application.properties index 8a74074cf5..9111491b58 100644 --- a/spring-kafka-2/src/main/resources/application.properties +++ b/spring-kafka-2/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.kafka.bootstrap-servers=localhost:9092,localhost:9093,localhost:9094,localhost:9095 +spring.kafka.bootstrap-servers=localhost:9092,localhost:9093,localhost:9094 message.topic.name=baeldung long.message.topic.name=longMessage greeting.topic.name=greeting diff --git a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java index 6059de9c45..72b77c360f 100644 --- a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java +++ b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java @@ -26,7 +26,8 @@ import com.baeldung.spring.kafka.dlt.listener.PaymentListenerDltRetryOnError; import com.baeldung.spring.kafka.dlt.listener.PaymentListenerNoDlt; import org.springframework.test.context.ActiveProfiles; -@SpringBootTest(classes = KafkaDltApplication.class) +@SpringBootTest(classes = KafkaDltApplication.class, + properties = "spring.kafka.bootstrap-servers=localhost:9095") @EmbeddedKafka( partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:9095", "port=9095" }, diff --git a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/multipletopics/KafkaMultipleTopicsIntegrationTest.java b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/multipletopics/KafkaMultipleTopicsIntegrationTest.java index e8aecf9549..088e1eba53 100644 --- a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/multipletopics/KafkaMultipleTopicsIntegrationTest.java +++ b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/multipletopics/KafkaMultipleTopicsIntegrationTest.java @@ -21,7 +21,8 @@ import org.springframework.kafka.test.context.EmbeddedKafka; import org.springframework.kafka.test.utils.ContainerTestUtils; import org.springframework.test.context.ActiveProfiles; -@SpringBootTest(classes = KafkaMultipleTopicsApplication.class) +@SpringBootTest(classes = KafkaMultipleTopicsApplication.class, + properties = "spring.kafka.bootstrap-servers=localhost:9099") @EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:9099", "port=9099" }) @ActiveProfiles("multipletopics") public class KafkaMultipleTopicsIntegrationTest { From 1b843fd34a24fef67979bcd1e84667f50a7af236 Mon Sep 17 00:00:00 2001 From: Manfred <77407079+manfred106@users.noreply.github.com> Date: Wed, 21 Feb 2024 03:31:55 +0000 Subject: [PATCH 15/17] BAEL-7296: Calling Custom Database Functions with JPA (#15869) --- .../spring-boot-persistence-4/pom.xml | 6 ++ .../customfunc/CustomFunctionApplication.java | 13 +++++ .../baeldung/customfunc/CustomH2Dialect.java | 25 ++++++++ .../customfunc/CustomHibernateConfig.java | 16 +++++ .../java/com/baeldung/customfunc/Product.java | 31 ++++++++++ .../customfunc/ProductRepository.java | 24 ++++++++ .../ProductRepositoryIntegrationTest.java | 58 +++++++++++++++++++ .../src/test/resources/product-data.sql | 17 ++++++ 8 files changed, 190 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomFunctionApplication.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomH2Dialect.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomHibernateConfig.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/Product.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/ProductRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/customfunc/ProductRepositoryIntegrationTest.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/test/resources/product-data.sql diff --git a/persistence-modules/spring-boot-persistence-4/pom.xml b/persistence-modules/spring-boot-persistence-4/pom.xml index 13cb4d5b82..acff937114 100644 --- a/persistence-modules/spring-boot-persistence-4/pom.xml +++ b/persistence-modules/spring-boot-persistence-4/pom.xml @@ -62,6 +62,11 @@ modelmapper ${modelmapper.version} + + commons-codec + commons-codec + ${commons-codec.version} + org.projectlombok lombok @@ -88,6 +93,7 @@ 3.7.0 2.16.0 3.2.0 + 1.16.1 1.18.30 diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomFunctionApplication.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomFunctionApplication.java new file mode 100644 index 0000000000..6e731501cb --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomFunctionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.customfunc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CustomFunctionApplication { + + public static void main(String[] args) { + SpringApplication.run(CustomFunctionApplication.class, args); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomH2Dialect.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomH2Dialect.java new file mode 100644 index 0000000000..56b26a8fcf --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomH2Dialect.java @@ -0,0 +1,25 @@ +package com.baeldung.customfunc; + +import org.hibernate.boot.model.FunctionContributions; +import org.hibernate.dialect.H2Dialect; + +import org.hibernate.query.sqm.function.FunctionKind; +import org.hibernate.query.sqm.function.SqmFunctionRegistry; +import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder; +import org.hibernate.type.spi.TypeConfiguration; + +public class CustomH2Dialect extends H2Dialect { + + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + SqmFunctionRegistry registry = functionContributions.getFunctionRegistry(); + TypeConfiguration types = functionContributions.getTypeConfiguration(); + + new PatternFunctionDescriptorBuilder(registry, "sha256hex", FunctionKind.NORMAL, "SHA256_HEX(?1)") + .setExactArgumentCount(1) + .setInvariantType(types.getBasicTypeForJavaType(String.class)) + .register(); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomHibernateConfig.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomHibernateConfig.java new file mode 100644 index 0000000000..424970f59a --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/CustomHibernateConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.customfunc; + +import org.springframework.context.annotation.Configuration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; + +import java.util.Map; + +@Configuration +public class CustomHibernateConfig implements HibernatePropertiesCustomizer { + + @Override + public void customize(Map hibernateProperties) { + hibernateProperties.put("hibernate.dialect", "com.baeldung.customfunc.CustomH2Dialect"); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/Product.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/Product.java new file mode 100644 index 0000000000..bfbea7a0c5 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/Product.java @@ -0,0 +1,31 @@ +package com.baeldung.customfunc; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "product") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(of = {"id"}) +@NamedStoredProcedureQuery( + name = "Product.sha256Hex", + procedureName = "SHA256_HEX", + parameters = @StoredProcedureParameter(mode = ParameterMode.IN, name = "value", type = String.class) +) +public class Product { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "product_id") + private Integer id; + + private String name; + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/ProductRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/ProductRepository.java new file mode 100644 index 0000000000..ea9ceba0ff --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/customfunc/ProductRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.customfunc; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.repository.query.Procedure; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface ProductRepository extends JpaRepository { + + @Procedure(name = "Product.sha256Hex") + String getSha256HexByNamedMapping(@Param("value") String value); + + @Query(value = "CALL SHA256_HEX(:value)", nativeQuery = true) + String getSha256HexByNativeCall(@Param("value") String value); + + @Query(value = "SELECT SHA256_HEX(name) FROM product", nativeQuery = true) + List getProductNameListInSha256HexByNativeSelect(); + + @Query(value = "SELECT sha256Hex(p.name) FROM Product p") + List getProductNameListInSha256Hex(); + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/customfunc/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/customfunc/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..a5b2ebe461 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/customfunc/ProductRepositoryIntegrationTest.java @@ -0,0 +1,58 @@ +package com.baeldung.customfunc; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest(classes = CustomFunctionApplication.class, properties = { + "spring.jpa.show-sql=true", + "spring.jpa.properties.hibernate.format_sql=true", + "spring.jpa.generate-ddl=true", + "spring.jpa.defer-datasource-initialization=true", + "spring.sql.init.data-locations=classpath:product-data.sql" +}) +@Transactional +public class ProductRepositoryIntegrationTest { + + private static final String TEXT = "Hand Grip Strengthener"; + private static final String EXPECTED_HASH_HEX = getSha256Hex(TEXT); + + @Autowired + private ProductRepository productRepository; + + private static String getSha256Hex(String value) { + return Hex.encodeHexString(DigestUtils.sha256(value.getBytes(StandardCharsets.UTF_8))); + } + + @Test + void whenGetSha256HexByNamedMapping_thenReturnCorrectHash() { + var hash = productRepository.getSha256HexByNamedMapping(TEXT); + assertThat(hash).isEqualTo(EXPECTED_HASH_HEX); + } + + @Test + void whenGetSha256HexByNativeCall_thenReturnCorrectHash() { + var hash = productRepository.getSha256HexByNativeCall(TEXT); + assertThat(hash).isEqualTo(EXPECTED_HASH_HEX); + } + + @Test + void whenCallGetSha256HexNative_thenReturnCorrectHash() { + var hashList = productRepository.getProductNameListInSha256HexByNativeSelect(); + assertThat(hashList.get(0)).isEqualTo(EXPECTED_HASH_HEX); + } + + @Test + void whenCallGetSha256Hex_thenReturnCorrectHash() { + var hashList = productRepository.getProductNameListInSha256Hex(); + assertThat(hashList.get(0)).isEqualTo(EXPECTED_HASH_HEX); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/test/resources/product-data.sql b/persistence-modules/spring-boot-persistence-4/src/test/resources/product-data.sql new file mode 100644 index 0000000000..7a59da68b7 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/test/resources/product-data.sql @@ -0,0 +1,17 @@ +CREATE ALIAS SHA256_HEX AS ' + import java.sql.*; + @CODE + String getSha256Hex(Connection conn, String value) throws SQLException { + var sql = "SELECT RAWTOHEX(HASH(''SHA-256'', ?))"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, value); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) { + return rs.getString(1); + } + } + return null; + } +'; + +INSERT INTO product(name) VALUES('Hand Grip Strengthener'); \ No newline at end of file From fcb6efbf0089b19f3a11d0559e6065e1cecbd2f1 Mon Sep 17 00:00:00 2001 From: Wynn Teo <49014791+wynnteo@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:36:34 +0800 Subject: [PATCH 16/17] BAEL-6622 (#15905) * BAEL-7490 read write file in separate thread * Change the to try resources * Update the code to sync with article * BAEL-6622 compare thenApply() and thenApplyAsync() * BAEL-6622 change to unit test * Tidy up the code --- .../ThenApplyAndThenApplyAsyncUnitTest.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/applyvsapplyasync/ThenApplyAndThenApplyAsyncUnitTest.java diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/applyvsapplyasync/ThenApplyAndThenApplyAsyncUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/applyvsapplyasync/ThenApplyAndThenApplyAsyncUnitTest.java new file mode 100644 index 0000000000..ee7f6d7a82 --- /dev/null +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/applyvsapplyasync/ThenApplyAndThenApplyAsyncUnitTest.java @@ -0,0 +1,91 @@ +package com.baeldung.concurrent.applyvsapplyasync; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ThenApplyAndThenApplyAsyncUnitTest { + + @Test + public void givenCompletableFuture_whenUsingThenApply_thenResultIsAsExpected() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> 5); + CompletableFuture thenApplyResultFuture = future.thenApply(num -> "Result: " + num); + + String thenApplyResult = thenApplyResultFuture.join(); + assertEquals("Result: 5", thenApplyResult); + } + + @Test + public void givenCompletableFuture_whenUsingThenApplyAsync_thenResultIsAsExpected() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> 5); + CompletableFuture thenApplyAsyncResultFuture = future.thenApplyAsync(num -> "Result: " + num); + + String thenApplyAsyncResult = thenApplyAsyncResultFuture.join(); + assertEquals("Result: 5", thenApplyAsyncResult); + } + + @Test + public void givenCompletableFuture_whenUsingThenApply_thenExceptionIsPropagated() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> 5); + CompletableFuture resultFuture = future.thenApply(num -> "Result: " + num / 0); + assertThrows(CompletionException.class, () -> resultFuture.join()); + } + + @Test + public void givenCompletableFuture_whenUsingThenApply_thenExceptionIsHandledAsExpected() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> 5); + CompletableFuture resultFuture = future.thenApply(num -> "Result: " + num / 0); + try { + // Accessing the result + String result = resultFuture.join(); + assertEquals("Result: 5", result); + } catch (CompletionException e) { + assertEquals("java.lang.ArithmeticException: / by zero", e.getMessage()); + System.err.println("Exception caught: " + e.getMessage()); + } + } + + @Test + public void givenCompletableFuture_whenUsingThenApplyAsync_thenExceptionIsHandledAsExpected() { + CompletableFuture future = CompletableFuture.supplyAsync(() -> 5); + CompletableFuture thenApplyAsyncResultFuture = future.thenApplyAsync(num -> "Result: " + num / 0); + + String result = thenApplyAsyncResultFuture.handle((res, error) -> { + if (error != null) { + // Handle the error appropriately, e.g., return a default value + return "Error occurred"; + } else { + return res; + } + }) + .join(); // Now join() won't throw the exception + assertEquals("Error occurred", result); + } + + @Test + public void givenCompletableFutureWithExecutor_whenUsingThenApplyAsync_thenThreadExecutesAsExpected() { + ExecutorService customExecutor = Executors.newFixedThreadPool(4); + + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return 5; + }, customExecutor); + + CompletableFuture resultFuture = future.thenApplyAsync(num -> "Result: " + num, customExecutor); + + String result = resultFuture.join(); + assertEquals("Result: 5", result); + + customExecutor.shutdown(); + } +} From c5a3c01108e2e288470497aff2e3247797058408 Mon Sep 17 00:00:00 2001 From: lucaCambi77 Date: Wed, 21 Feb 2024 04:43:07 +0100 Subject: [PATCH 17/17] Check if two strings are rotations of each other [BAEL-7493] (#15864) * feat: string rotation * fix: test names --- .../stringrotation/StringRotation.java | 123 ++++++++++++++++++ .../StringRotationUnitTest.java | 61 +++++++++ 2 files changed, 184 insertions(+) create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/stringrotation/StringRotation.java create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/stringrotation/StringRotationUnitTest.java diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/stringrotation/StringRotation.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/stringrotation/StringRotation.java new file mode 100644 index 0000000000..862c745c9e --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/stringrotation/StringRotation.java @@ -0,0 +1,123 @@ +package com.baeldung.algorithms.stringrotation; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class StringRotation { + + public static boolean doubledOriginContainsRotation(String origin, String rotation) { + if (origin.length() == rotation.length()) { + return origin.concat(origin) + .contains(rotation); + } + + return false; + } + + public static boolean isRotationUsingCommonStartWithOrigin(String origin, String rotation) { + + if (origin.length() == rotation.length()) { + + List indexes = IntStream.range(0, origin.length()) + .filter(i -> rotation.charAt(i) == origin.charAt(0)) + .boxed() + .collect(Collectors.toList()); + + for (int startingAt : indexes) { + if (isRotation(startingAt, rotation, origin)) { + return true; + } + } + } + + return false; + } + + static boolean isRotation(int startingAt, String rotation, String origin) { + + for (int i = 0; i < origin.length(); i++) { + if (rotation.charAt((startingAt + i) % origin.length()) != origin.charAt(i)) { + return false; + } + } + + return true; + } + + public static boolean isRotationUsingQueue(String origin, String rotation) { + + if (origin.length() == rotation.length()) { + return checkWithQueue(origin, rotation); + } + + return false; + } + + static boolean checkWithQueue(String origin, String rotation) { + + if (origin.length() == rotation.length()) { + + Queue originQueue = getCharactersQueue(origin); + + Queue rotationQueue = getCharactersQueue(rotation); + + int k = rotation.length(); + while (k > 0 && null != rotationQueue.peek()) { + k--; + char ch = rotationQueue.peek(); + rotationQueue.remove(); + rotationQueue.add(ch); + if (rotationQueue.equals(originQueue)) { + return true; + } + } + } + + return false; + } + + static Queue getCharactersQueue(String origin) { + return origin.chars() + .mapToObj(c -> (char) c) + .collect(Collectors.toCollection(LinkedList::new)); + } + + public static boolean isRotationUsingSuffixAndPrefix(String origin, String rotation) { + + if (origin.length() == rotation.length()) { + return checkPrefixAndSuffix(origin, rotation); + } + + return false; + } + + static boolean checkPrefixAndSuffix(String origin, String rotation) { + if (origin.length() == rotation.length()) { + + for (int i = 0; i < origin.length(); i++) { + if (origin.charAt(i) == rotation.charAt(0)) { + if (checkRotationPrefixWithOriginSuffix(origin, rotation, i)) { + if (checkOriginPrefixWithRotationSuffix(origin, rotation, i)) + return true; + } + } + } + + } + + return false; + } + + private static boolean checkRotationPrefixWithOriginSuffix(String origin, String rotation, int i) { + return origin.substring(i) + .equals(rotation.substring(0, origin.length() - i)); + } + + private static boolean checkOriginPrefixWithRotationSuffix(String origin, String rotation, int i) { + return origin.substring(0, i) + .equals(rotation.substring(origin.length() - i)); + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/stringrotation/StringRotationUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/stringrotation/StringRotationUnitTest.java new file mode 100644 index 0000000000..5558c6ca9f --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/stringrotation/StringRotationUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.algorithms.stringrotation; + +import static com.baeldung.algorithms.stringrotation.StringRotation.doubledOriginContainsRotation; +import static com.baeldung.algorithms.stringrotation.StringRotation.isRotationUsingCommonStartWithOrigin; +import static com.baeldung.algorithms.stringrotation.StringRotation.isRotationUsingQueue; +import static com.baeldung.algorithms.stringrotation.StringRotation.isRotationUsingSuffixAndPrefix; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class StringRotationUnitTest { + + @Test + void givenOriginAndRotationInput_whenCheckIfOriginContainsRotation_thenIsRotation() { + assertTrue(doubledOriginContainsRotation("abcd", "cdab")); + assertTrue(doubledOriginContainsRotation("abcd", "abcd")); + } + + @Test + void givenOriginAndRotationInput_whenCheckIfOriginContainsRotation_thenNoRotation() { + assertFalse(doubledOriginContainsRotation("abcd", "bbbb")); + assertFalse(doubledOriginContainsRotation("abcd", "abcde")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingCommonStartWithOrigin_thenIsRotation() { + assertTrue(isRotationUsingCommonStartWithOrigin("abcd", "cdab")); + assertTrue(isRotationUsingCommonStartWithOrigin("abcd", "abcd")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingCommonStartWithOrigin_thenNoRotation() { + assertFalse(isRotationUsingCommonStartWithOrigin("abcd", "bbbb")); + assertFalse(isRotationUsingCommonStartWithOrigin("abcd", "abcde")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingUsingQueues_thenIsRotation() { + assertTrue(isRotationUsingQueue("abcd", "cdab")); + assertTrue(isRotationUsingQueue("abcd", "abcd")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingUsingQueues_thenNoRotation() { + assertFalse(isRotationUsingQueue("abcd", "bbbb")); + assertFalse(isRotationUsingQueue("abcd", "abcde")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingUsingSuffixAndPrefix_thenIsRotation() { + assertTrue(isRotationUsingSuffixAndPrefix("abcd", "cdab")); + assertTrue(isRotationUsingSuffixAndPrefix("abcd", "abcd")); + } + + @Test + void givenOriginAndRotationInput_whenCheckingUsingSuffixAndPrefix_thenNoRotation() { + assertFalse(isRotationUsingSuffixAndPrefix("abcd", "bbbb")); + assertFalse(isRotationUsingSuffixAndPrefix("abcd", "abcde")); + } +}