From 16dc441ac5593e31e74ee7d0a96f5cf696333d72 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 14 Jan 2024 12:38:26 -0500 Subject: [PATCH 01/92] implementation for bael-7192 --- logging-modules/loki-logback/README.md | 1 + logging-modules/loki-logback/pom.xml | 65 +++++++++++++++++++ .../java/com/baeldung/loki/DemoService.java | 15 +++++ .../src/main/resources/logback-spring.xml | 55 ++++++++++++++++ .../com/baeldung/loki/DemoServiceTest.java | 49 ++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 logging-modules/loki-logback/README.md create mode 100644 logging-modules/loki-logback/pom.xml create mode 100644 logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java create mode 100644 logging-modules/loki-logback/src/main/resources/logback-spring.xml create mode 100644 logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java diff --git a/logging-modules/loki-logback/README.md b/logging-modules/loki-logback/README.md new file mode 100644 index 0000000000..e320af31b4 --- /dev/null +++ b/logging-modules/loki-logback/README.md @@ -0,0 +1 @@ +### Relevant Articles: \ No newline at end of file diff --git a/logging-modules/loki-logback/pom.xml b/logging-modules/loki-logback/pom.xml new file mode 100644 index 0000000000..7cc052b06f --- /dev/null +++ b/logging-modules/loki-logback/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + logback + 0.1-SNAPSHOT + logback + + + org.springframework.boot + spring-boot-starter-parent + 3.2.0 + + + + + + com.github.loki4j + loki-logback-appender + ${loki-logback.version} + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.springframework.boot + spring-boot-starter-test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + + 0.1.5 + 1.4.2 + 2.0.4 + 1.18.22 + 5.6.0 + + + \ No newline at end of file diff --git a/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java b/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java new file mode 100644 index 0000000000..e9071c0de9 --- /dev/null +++ b/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java @@ -0,0 +1,15 @@ +package com.baeldung.loki; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class DemoService { + + private final Logger LOG = LoggerFactory.getLogger(DemoService.class); + + public void log() { + LOG.info("DemoService.log invoked"); + } +} diff --git a/logging-modules/loki-logback/src/main/resources/logback-spring.xml b/logging-modules/loki-logback/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..fa4b92f2f6 --- /dev/null +++ b/logging-modules/loki-logback/src/main/resources/logback-spring.xml @@ -0,0 +1,55 @@ + + + + + + + + + { + "level":"%level", + "class":"%logger{36}", + "thread":"%thread", + "message": "%message", + "requestId": "%X{X-Request-ID}" + } + + + + + + + + + + + http://localhost:3100/loki/api/v1/push + + + + + + + + { + "level":"%level", + "class":"%logger{36}", + "thread":"%thread", + "message": "%message", + "requestId": "%X{X-Request-ID}" + } + + + + + + + + + + + \ No newline at end of file diff --git a/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java b/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java new file mode 100644 index 0000000000..be88b80445 --- /dev/null +++ b/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java @@ -0,0 +1,49 @@ +package com.baeldung.loki; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.text.ParseException; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; + +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = DemoService.class) +public class DemoServiceTest { + + @Mock + Appender appender; + + @Captor + ArgumentCaptor captor; + + @Test + public void givenLokiAppender_whenSampleServiceInvoked_ThenCaptureInfoLog() throws ParseException { + ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + when(appender.getName()).thenReturn("loki-logback-appender"); + logger.addAppender(appender); + + DemoService service = new DemoService(); + service.log(); + + verify(appender, times(1)).doAppend(captor.capture()); + List allValues = captor.getAllValues(); + assertEquals(1, allValues.size()); + ILoggingEvent event = allValues.get(0); + assertEquals(event.getLevel(), Level.INFO); + assertEquals("DemoService.log invoked", event.getFormattedMessage()); + } +} From d7527a382e328388ceaf844a0b69f69461e216bc Mon Sep 17 00:00:00 2001 From: Sam Gardner Date: Thu, 22 Feb 2024 15:11:26 +0000 Subject: [PATCH 02/92] BAEL-7513 Merge overlapping intervals in collection --- .../algorithms/mergeintervals/Interval.java | 37 +++++++++++++++++++ .../MergeOverlappingIntervals.java | 29 +++++++++++++++ .../MergeIntervalsUnitTest.java | 30 +++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java new file mode 100644 index 0000000000..1b13b8b279 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java @@ -0,0 +1,37 @@ +package com.baeldung.algorithms.mergeintervals; + +import java.util.Objects; + +public class Interval { + int start; + int end; + + Interval(int start, int end) { + this.start = start; + this.end = end; + } + + public void setEnd(int end) { + this.end = end; + } + + @Override + public String toString() { + return "Interval{" + "start=" + start + ", end=" + end + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Interval interval = (Interval) o; + return start == interval.start && end == interval.end; + } + + @Override + public int hashCode() { + return Objects.hash(start, end); + } +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java new file mode 100644 index 0000000000..ba424772d5 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.mergeintervals; + +import java.util.ArrayList; +import java.util.List; + +public class MergeOverlappingIntervals { + + public List doMerge(List intervals) { + // Sort the intervals based on start time + intervals.sort((one, two) -> one.start - two.start); + + // Create somewhere to put the merged list, start it off with the earliest starting interval + ArrayList merged = new ArrayList<>(); + merged.add(intervals.get(0)); + + // Loop over each interval and merge if start time is before the end time of the + // previous interval + intervals.forEach(interval -> { + if (merged.get(merged.size() - 1).end > interval.start) { + merged.get(merged.size() - 1).setEnd(interval.end); + } else { + merged.add(interval); + } + }); + + return merged; + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java new file mode 100644 index 0000000000..5f15fe00f6 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.algorithms.mergeintervals; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +class MergeIntervalsUnitTest { + + private ArrayList intervals = new ArrayList<>(Arrays.asList( + new Interval(2, 5), + new Interval(13, 20), + new Interval(11, 15), + new Interval(1, 3) + )); + private ArrayList intervalsMerged = new ArrayList<>(Arrays.asList( + new Interval(1, 5), + new Interval(11, 20) + )); + + @Test + void givenIntervals_whenMerging_thenReturnMergedIntervals() { + MergeOverlappingIntervals merger = new MergeOverlappingIntervals(); + ArrayList result = (ArrayList) merger.doMerge(intervals); + assertArrayEquals(intervalsMerged.toArray(), result.toArray()); + } + +} From 433a32489c6e1eb30580cf4b3226b617ba262109 Mon Sep 17 00:00:00 2001 From: Sam Gardner Date: Thu, 22 Feb 2024 15:13:15 +0000 Subject: [PATCH 03/92] BAEL-7513 Add missing newline to Interval.java --- .../java/com/baeldung/algorithms/mergeintervals/Interval.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java index 1b13b8b279..f926d578be 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java @@ -34,4 +34,4 @@ public class Interval { public int hashCode() { return Objects.hash(start, end); } -} \ No newline at end of file +} From e50e8e96a0931fca35ff41e447f540cfc5b5a7e5 Mon Sep 17 00:00:00 2001 From: balasr3 Date: Sat, 24 Feb 2024 16:52:26 +0000 Subject: [PATCH 04/92] BAEL-7272: Removed CodeCustomizer config which is not mandatory for Global serialization/deserialization config --- .../config/CodecCustomizerConfig.java | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/custom/deserialization/config/CodecCustomizerConfig.java diff --git a/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/custom/deserialization/config/CodecCustomizerConfig.java b/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/custom/deserialization/config/CodecCustomizerConfig.java deleted file mode 100644 index ef3eb1e97f..0000000000 --- a/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/custom/deserialization/config/CodecCustomizerConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.custom.deserialization.config; - -import org.springframework.boot.web.codec.CodecCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.http.codec.CodecConfigurer; -import org.springframework.http.codec.json.Jackson2JsonDecoder; -import org.springframework.http.codec.json.Jackson2JsonEncoder; -import org.springframework.util.MimeType; - -import com.fasterxml.jackson.databind.ObjectMapper; - -@Configuration -public class CodecCustomizerConfig { - - @Bean - public CodecCustomizer codecCustomizer(ObjectMapper customObjectMapper) { - return configurer -> { - MimeType mimeType = MimeType.valueOf(MediaType.APPLICATION_JSON_VALUE); - CodecConfigurer.CustomCodecs customCodecs = configurer.customCodecs(); - customCodecs.register(new Jackson2JsonDecoder(customObjectMapper, mimeType)); - customCodecs.register(new Jackson2JsonEncoder(customObjectMapper, mimeType)); - }; - } - -} From a34edd524d6793d6ac984ce18ac7e582d5731f75 Mon Sep 17 00:00:00 2001 From: Maiklins Date: Sat, 9 Mar 2024 11:58:10 +0100 Subject: [PATCH 05/92] Update README.md --- spring-security-modules/spring-security-core-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-modules/spring-security-core-2/README.md b/spring-security-modules/spring-security-core-2/README.md index 5f54dc1a50..306d0865b0 100644 --- a/spring-security-modules/spring-security-core-2/README.md +++ b/spring-security-modules/spring-security-core-2/README.md @@ -9,6 +9,7 @@ This module contains articles about core Spring Security - [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver) - [A Custom Spring SecurityConfigurer](https://www.baeldung.com/spring-security-custom-configurer) - [HttpSecurity vs. WebSecurity in Spring Security](https://www.baeldung.com/spring-security-httpsecurity-vs-websecurity) +- [Spring Security AuthorizationManager](https://www.baeldung.com/spring-security-authorizationmanager) ### Build the Project From 82ca2b8b92f811ade05f0f10817ea0ab53a8d6cd Mon Sep 17 00:00:00 2001 From: danielmcnally285 <144589379+danielmcnally285@users.noreply.github.com> Date: Sat, 16 Mar 2024 12:23:28 +0000 Subject: [PATCH 06/92] last n characters from string unit tests --- .../LastNCharactersUnitTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java new file mode 100644 index 0000000000..1dd45b0d89 --- /dev/null +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.lastncharacters; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class LastNCharactersUnitTest { + + private String s; + private int n; + + @Test + void givenString_whenUsingIntStreamAsStreamSource_thenObtainLastNCharacters() { + String result = s.chars() + .mapToObj(c -> (char) c) + .skip(s.length() - n) + .map(String::valueOf) + .collect(Collectors.joining()); + assertThat(result).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingOneArgSubstringMethod_thenObtainLastNCharacters() { + int beginIndex = s.length() - n; + assertThat(s.substring(beginIndex)).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingStreamOfCharactersAsSource_thenObtainLastNCharacters() { + String result = Arrays.stream(ArrayUtils.toObject(s.toCharArray())) + .skip(s.length() - n) + .map(String::valueOf) + .collect(Collectors.joining()); + assertThat(result).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingStringUtilsRight_thenObtainLastNCharacters() { + assertThat(StringUtils.right(s, n)).isEqualTo("2024"); + } + + @Test + void givenString_whenUsingTwoArgSubstringMethod_thenObtainLastNCharacters() { + int beginIndex = s.length() - n; + String result = s.substring(beginIndex, s.length()); + assertThat(result).isEqualTo("2024"); + } + + @BeforeEach + void init() { + s = "10-03-2024"; + n = 4; + } +} \ No newline at end of file From 96450ee79d74b59640163adfa301108b64b21420 Mon Sep 17 00:00:00 2001 From: danielmcnally285 <144589379+danielmcnally285@users.noreply.github.com> Date: Sat, 16 Mar 2024 12:34:35 +0000 Subject: [PATCH 07/92] add new lines before assert statements --- .../com/baeldung/lastncharacters/LastNCharactersUnitTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java index 1dd45b0d89..d2b5227077 100644 --- a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java @@ -22,12 +22,14 @@ public class LastNCharactersUnitTest { .skip(s.length() - n) .map(String::valueOf) .collect(Collectors.joining()); + assertThat(result).isEqualTo("2024"); } @Test void givenString_whenUsingOneArgSubstringMethod_thenObtainLastNCharacters() { int beginIndex = s.length() - n; + assertThat(s.substring(beginIndex)).isEqualTo("2024"); } @@ -37,6 +39,7 @@ public class LastNCharactersUnitTest { .skip(s.length() - n) .map(String::valueOf) .collect(Collectors.joining()); + assertThat(result).isEqualTo("2024"); } @@ -49,6 +52,7 @@ public class LastNCharactersUnitTest { void givenString_whenUsingTwoArgSubstringMethod_thenObtainLastNCharacters() { int beginIndex = s.length() - n; String result = s.substring(beginIndex, s.length()); + assertThat(result).isEqualTo("2024"); } From 3563a3e35a4ed62976fbdf368e9d5b8ae970ec93 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 17 Mar 2024 20:54:28 -0400 Subject: [PATCH 08/92] adding live test --- .../spring-boot-logging-loki/README.md | 1 + .../spring-boot-logging-loki/pom.xml | 41 +++++++++ .../java/com/baeldung/loki/DemoService.java | 15 ++++ ...pringBootLogbackExtensionsApplication.java | 22 +++++ .../src/main/resources/logback-spring.xml | 48 +++++++++++ .../baeldung/loki/DemoServiceLiveTest.java | 86 +++++++++++++++++++ 6 files changed, 213 insertions(+) create mode 100644 spring-boot-modules/spring-boot-logging-loki/README.md create mode 100644 spring-boot-modules/spring-boot-logging-loki/pom.xml create mode 100644 spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java create mode 100644 spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java create mode 100644 spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml create mode 100644 spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java diff --git a/spring-boot-modules/spring-boot-logging-loki/README.md b/spring-boot-modules/spring-boot-logging-loki/README.md new file mode 100644 index 0000000000..e320af31b4 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/README.md @@ -0,0 +1 @@ +### Relevant Articles: \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-logging-loki/pom.xml b/spring-boot-modules/spring-boot-logging-loki/pom.xml new file mode 100644 index 0000000000..fa568119fb --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + spring-boot-logging-loki + 0.1-SNAPSHOT + loki + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + com.github.loki4j + loki-logback-appender + ${loki-logback.version} + + + org.springframework.boot + spring-boot-starter-test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + + 1.4.2 + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java new file mode 100644 index 0000000000..236e5b530c --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java @@ -0,0 +1,15 @@ +package com.baeldung.loki; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class DemoService { + + private final Logger LOG = LoggerFactory.getLogger(DemoService.class); + + public void log() { + LOG.info("DemoService.log invoked!!!"); + } +} diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java new file mode 100644 index 0000000000..28e455a7ea --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java @@ -0,0 +1,22 @@ +package com.baeldung.extensions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootLogbackExtensionsApplication { + + private static final Logger logger = LoggerFactory.getLogger(SpringBootLogbackExtensionsApplication.class); + + public static void main(String[] args) { + SpringApplication.run(SpringBootLogbackExtensionsApplication.class, args); + + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + logger.warn("Warn log message"); + logger.trace("Trace log message"); + } +} diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..c4711c1680 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml @@ -0,0 +1,48 @@ + + + + + + + + + { + "level":"%level", + "class":"%logger{36}", + "thread":"%thread", + "message": "%message", + "requestId": "%X{X-Request-ID}" + } + + + + + + + http://localhost:3100/loki/api/v1/push + + + + + + { + "level":"%level", + "class":"%logger{36}", + "thread":"%thread", + "message": "%message", + "requestId": "%X{X-Request-ID}" + } + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java new file mode 100644 index 0000000000..cf6091c2aa --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java @@ -0,0 +1,86 @@ +package com.baeldung.loki; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.verify; + +import java.net.URI; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest(classes = DemoService.class) +public class DemoServiceLiveTest { + + @Test + public void givenLokiContainerRunning_whenDemoServiceInvoked_thenLokiAppenderCollectLogs() throws JsonProcessingException, InterruptedException { + DemoService service = new DemoService(); + service.log(); + Thread.sleep(2000); + String baseUrl = "http://localhost:3100/loki/api/v1/query_range"; + // Set up query parameters + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + String query = "{level=\"INFO\"} |= `DemoService.log invoked!!!`"; + // Get current time in UTC + LocalDateTime currentDateTime = LocalDateTime.now(ZoneOffset.UTC); + String current_time_est = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + + LocalDateTime tenMinsAgo = currentDateTime.minusMinutes(10); + String start_time_est = tenMinsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + System.out.println(start_time_est); + + URI uri = UriComponentsBuilder.fromUriString(baseUrl) + .queryParam("query", query) + .queryParam("start", start_time_est) + .queryParam("end", current_time_est) + .build() + .toUri(); + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.exchange( + uri, + HttpMethod.GET, + new HttpEntity<>(headers), + String.class + ); + + List messages = new ArrayList<>(); + ObjectMapper objectMapper = new ObjectMapper(); + if (response.getStatusCode() == HttpStatus.OK) { + String responseBody = response.getBody(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + JsonNode result = jsonNode.get("data").get("result").get(0).get("values"); + result.iterator().forEachRemaining(e-> { + Iterator elements = e.elements(); + elements.forEachRemaining(f -> + messages.add(f.toString()) + ); + }); + } else { + System.out.println("Error: " + response.getStatusCodeValue()); + } + + String expected = "DemoService.log invoked!!!"; + assertTrue(messages.stream().anyMatch(e -> e.contains(expected))); + } +} From 9439463838157c10259e3b70cc242a1aedc900fc Mon Sep 17 00:00:00 2001 From: danielmcnally285 <144589379+danielmcnally285@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:02:44 +0000 Subject: [PATCH 09/92] move BeforeEach to top of class --- .../lastncharacters/LastNCharactersUnitTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java index d2b5227077..0d30653082 100644 --- a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/lastncharacters/LastNCharactersUnitTest.java @@ -15,6 +15,12 @@ public class LastNCharactersUnitTest { private String s; private int n; + @BeforeEach + void init() { + s = "10-03-2024"; + n = 4; + } + @Test void givenString_whenUsingIntStreamAsStreamSource_thenObtainLastNCharacters() { String result = s.chars() @@ -55,10 +61,4 @@ public class LastNCharactersUnitTest { assertThat(result).isEqualTo("2024"); } - - @BeforeEach - void init() { - s = "10-03-2024"; - n = 4; - } } \ No newline at end of file From 329a01ec93bb6786befe6e62829ded80cd13fe4a Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 17 Mar 2024 20:58:11 -0400 Subject: [PATCH 10/92] deleting / moving project dir --- logging-modules/loki-logback/README.md | 1 - logging-modules/loki-logback/pom.xml | 65 ------------------- .../java/com/baeldung/loki/DemoService.java | 15 ----- .../src/main/resources/logback-spring.xml | 55 ---------------- .../com/baeldung/loki/DemoServiceTest.java | 49 -------------- .../spring-boot-logging-loki/pom.xml | 6 -- .../java/com/baeldung/loki/DemoService.java | 2 +- ...pringBootLogbackExtensionsApplication.java | 22 ------- .../src/main/resources/logback-spring.xml | 16 ----- .../baeldung/loki/DemoServiceLiveTest.java | 7 +- 10 files changed, 5 insertions(+), 233 deletions(-) delete mode 100644 logging-modules/loki-logback/README.md delete mode 100644 logging-modules/loki-logback/pom.xml delete mode 100644 logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java delete mode 100644 logging-modules/loki-logback/src/main/resources/logback-spring.xml delete mode 100644 logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java delete mode 100644 spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java diff --git a/logging-modules/loki-logback/README.md b/logging-modules/loki-logback/README.md deleted file mode 100644 index e320af31b4..0000000000 --- a/logging-modules/loki-logback/README.md +++ /dev/null @@ -1 +0,0 @@ -### Relevant Articles: \ No newline at end of file diff --git a/logging-modules/loki-logback/pom.xml b/logging-modules/loki-logback/pom.xml deleted file mode 100644 index 7cc052b06f..0000000000 --- a/logging-modules/loki-logback/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - logback - 0.1-SNAPSHOT - logback - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0 - - - - - - com.github.loki4j - loki-logback-appender - ${loki-logback.version} - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.springframework.boot - spring-boot-starter-test - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-devtools - runtime - true - - - - - 0.1.5 - 1.4.2 - 2.0.4 - 1.18.22 - 5.6.0 - - - \ No newline at end of file diff --git a/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java b/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java deleted file mode 100644 index e9071c0de9..0000000000 --- a/logging-modules/loki-logback/src/main/java/com/baeldung/loki/DemoService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.loki; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -@Service -public class DemoService { - - private final Logger LOG = LoggerFactory.getLogger(DemoService.class); - - public void log() { - LOG.info("DemoService.log invoked"); - } -} diff --git a/logging-modules/loki-logback/src/main/resources/logback-spring.xml b/logging-modules/loki-logback/src/main/resources/logback-spring.xml deleted file mode 100644 index fa4b92f2f6..0000000000 --- a/logging-modules/loki-logback/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - { - "level":"%level", - "class":"%logger{36}", - "thread":"%thread", - "message": "%message", - "requestId": "%X{X-Request-ID}" - } - - - - - - - - - - - http://localhost:3100/loki/api/v1/push - - - - - - - - { - "level":"%level", - "class":"%logger{36}", - "thread":"%thread", - "message": "%message", - "requestId": "%X{X-Request-ID}" - } - - - - - - - - - - - \ No newline at end of file diff --git a/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java b/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java deleted file mode 100644 index be88b80445..0000000000 --- a/logging-modules/loki-logback/src/test/java/com/baeldung/loki/DemoServiceTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.loki; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.text.ParseException; -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Appender; - -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest(classes = DemoService.class) -public class DemoServiceTest { - - @Mock - Appender appender; - - @Captor - ArgumentCaptor captor; - - @Test - public void givenLokiAppender_whenSampleServiceInvoked_ThenCaptureInfoLog() throws ParseException { - ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - when(appender.getName()).thenReturn("loki-logback-appender"); - logger.addAppender(appender); - - DemoService service = new DemoService(); - service.log(); - - verify(appender, times(1)).doAppend(captor.capture()); - List allValues = captor.getAllValues(); - assertEquals(1, allValues.size()); - ILoggingEvent event = allValues.get(0); - assertEquals(event.getLevel(), Level.INFO); - assertEquals("DemoService.log invoked", event.getFormattedMessage()); - } -} diff --git a/spring-boot-modules/spring-boot-logging-loki/pom.xml b/spring-boot-modules/spring-boot-logging-loki/pom.xml index fa568119fb..5b2887562b 100644 --- a/spring-boot-modules/spring-boot-logging-loki/pom.xml +++ b/spring-boot-modules/spring-boot-logging-loki/pom.xml @@ -27,12 +27,6 @@ org.springframework.boot spring-boot-starter-web - - org.springframework.boot - spring-boot-devtools - runtime - true - diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java index 236e5b530c..e9071c0de9 100644 --- a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java @@ -10,6 +10,6 @@ public class DemoService { private final Logger LOG = LoggerFactory.getLogger(DemoService.class); public void log() { - LOG.info("DemoService.log invoked!!!"); + LOG.info("DemoService.log invoked"); } } diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java deleted file mode 100644 index 28e455a7ea..0000000000 --- a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/SpringBootLogbackExtensionsApplication.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.extensions; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringBootLogbackExtensionsApplication { - - private static final Logger logger = LoggerFactory.getLogger(SpringBootLogbackExtensionsApplication.class); - - public static void main(String[] args) { - SpringApplication.run(SpringBootLogbackExtensionsApplication.class, args); - - logger.debug("Debug log message"); - logger.info("Info log message"); - logger.error("Error log message"); - logger.warn("Warn log message"); - logger.trace("Trace log message"); - } -} diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml index c4711c1680..1ba53d7278 100644 --- a/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/resources/logback-spring.xml @@ -2,21 +2,6 @@ - - - - - { - "level":"%level", - "class":"%logger{36}", - "thread":"%thread", - "message": "%message", - "requestId": "%X{X-Request-ID}" - } - - - - http://localhost:3100/loki/api/v1/push @@ -41,7 +26,6 @@ - diff --git a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java index cf6091c2aa..c99a6e6766 100644 --- a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java +++ b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java @@ -37,17 +37,18 @@ public class DemoServiceLiveTest { service.log(); Thread.sleep(2000); String baseUrl = "http://localhost:3100/loki/api/v1/query_range"; + // Set up query parameters HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - String query = "{level=\"INFO\"} |= `DemoService.log invoked!!!`"; + String query = "{level=\"INFO\"} |= `DemoService.log invoked`"; + // Get current time in UTC LocalDateTime currentDateTime = LocalDateTime.now(ZoneOffset.UTC); String current_time_est = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); LocalDateTime tenMinsAgo = currentDateTime.minusMinutes(10); String start_time_est = tenMinsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); - System.out.println(start_time_est); URI uri = UriComponentsBuilder.fromUriString(baseUrl) .queryParam("query", query) @@ -80,7 +81,7 @@ public class DemoServiceLiveTest { System.out.println("Error: " + response.getStatusCodeValue()); } - String expected = "DemoService.log invoked!!!"; + String expected = "DemoService.log invoked"; assertTrue(messages.stream().anyMatch(e -> e.contains(expected))); } } From 12f1cdc1a3732171fea1f38388dc10006d15a9e3 Mon Sep 17 00:00:00 2001 From: technoddy Date: Wed, 20 Mar 2024 23:22:41 -0400 Subject: [PATCH 11/92] feedback updates --- .../baeldung/loki/DemoServiceLiveTest.java | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java index c99a6e6766..4c44888dca 100644 --- a/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java +++ b/spring-boot-modules/spring-boot-logging-loki/src/test/java/com/baeldung/loki/DemoServiceLiveTest.java @@ -1,8 +1,7 @@ package com.baeldung.loki; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.verify; import java.net.URI; import java.time.LocalDateTime; @@ -31,13 +30,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootTest(classes = DemoService.class) public class DemoServiceLiveTest { + /** + * This test assumes that loki service is already up. + * For more details please check section #2 Running Loki and Grafana Service + * Which spin up Loki server using docker-compose + */ @Test public void givenLokiContainerRunning_whenDemoServiceInvoked_thenLokiAppenderCollectLogs() throws JsonProcessingException, InterruptedException { DemoService service = new DemoService(); service.log(); - Thread.sleep(2000); - String baseUrl = "http://localhost:3100/loki/api/v1/query_range"; + String baseUrl = "http://localhost:3100/loki/api/v1/query_range"; // Set up query parameters HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); @@ -45,43 +48,38 @@ public class DemoServiceLiveTest { // Get current time in UTC LocalDateTime currentDateTime = LocalDateTime.now(ZoneOffset.UTC); - String current_time_est = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + String currentTimeUtc = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); - LocalDateTime tenMinsAgo = currentDateTime.minusMinutes(10); - String start_time_est = tenMinsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + LocalDateTime tenMinsAgo = currentDateTime.minusMinutes(10); + String startTimeUtc = tenMinsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); URI uri = UriComponentsBuilder.fromUriString(baseUrl) .queryParam("query", query) - .queryParam("start", start_time_est) - .queryParam("end", current_time_est) + .queryParam("start", startTimeUtc) + .queryParam("end", currentTimeUtc) .build() .toUri(); RestTemplate restTemplate = new RestTemplate(); - ResponseEntity response = restTemplate.exchange( - uri, - HttpMethod.GET, - new HttpEntity<>(headers), - String.class - ); + ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(headers), String.class); List messages = new ArrayList<>(); ObjectMapper objectMapper = new ObjectMapper(); - if (response.getStatusCode() == HttpStatus.OK) { - String responseBody = response.getBody(); - JsonNode jsonNode = objectMapper.readTree(responseBody); - JsonNode result = jsonNode.get("data").get("result").get(0).get("values"); - result.iterator().forEachRemaining(e-> { + assertEquals(response.getStatusCode(), HttpStatus.OK); + + String responseBody = response.getBody(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + JsonNode result = jsonNode.get("data") + .get("result") + .get(0) + .get("values"); + result.iterator() + .forEachRemaining(e -> { Iterator elements = e.elements(); - elements.forEachRemaining(f -> - messages.add(f.toString()) - ); + elements.forEachRemaining(f -> messages.add(f.toString())); }); - } else { - System.out.println("Error: " + response.getStatusCodeValue()); - } String expected = "DemoService.log invoked"; - assertTrue(messages.stream().anyMatch(e -> e.contains(expected))); + assertThat(messages).anyMatch(e -> e.contains(expected)); } } From 47e4316d01d574c3af20ab72e06fe555e506c91e Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sat, 23 Mar 2024 17:23:38 +0100 Subject: [PATCH 12/92] [map-to-value->Set-of-keys] Map -> Map> --- .../core-java-collections-maps-8/README.md | 1 + .../core-java-collections-maps-8/pom.xml | 29 ++++ ...rtMapKeyValueToMapValueKeySetUnitTest.java | 127 ++++++++++++++++++ core-java-modules/pom.xml | 1 + 4 files changed, 158 insertions(+) create mode 100644 core-java-modules/core-java-collections-maps-8/README.md create mode 100644 core-java-modules/core-java-collections-maps-8/pom.xml create mode 100644 core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java diff --git a/core-java-modules/core-java-collections-maps-8/README.md b/core-java-modules/core-java-collections-maps-8/README.md new file mode 100644 index 0000000000..0dd8c780d6 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/README.md @@ -0,0 +1 @@ +## Relevant Articles: \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-8/pom.xml b/core-java-modules/core-java-collections-maps-8/pom.xml new file mode 100644 index 0000000000..8c4454cf0f --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + core-java-collections-maps-8 + core-java-collections-maps-8 + jar + + + core-java-modules + com.baeldung.core-java-modules + 0.0.1-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + diff --git a/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java b/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java new file mode 100644 index 0000000000..a7491fd257 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-8/src/test/java/com/baeldung/map/valuetokeyset/ConvertMapKeyValueToMapValueKeySetUnitTest.java @@ -0,0 +1,127 @@ +package com.baeldung.map.valuetokeyset; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toSet; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +public class ConvertMapKeyValueToMapValueKeySetUnitTest { + + private static final Map INPUT_MAP = Map.of( + // @formatter:off + "Kai", "Linux", + "Eric", "MacOS", + "Kevin", "Windows", + "Liam", "MacOS", + "David", "Linux", + "Saajan", "Windows", + "Loredana", "MacOS" + // @formatter:on + ); + + private static final Map> EXPECTED = Map.of( + // @formatter:off + "Linux", Set.of("Kai", "David"), + "Windows", Set.of("Saajan", "Kevin"), + "MacOS", Set.of("Eric", "Liam", "Loredana") + // @formatter:on + ); + + private static final Map INPUT_MAP_WITH_NULLS = new HashMap(INPUT_MAP) {{ + put("Tom", null); + put("Jerry", null); + put(null, null); + }}; + + private static final Map> EXPECTED_WITH_NULLS = new HashMap>(EXPECTED) {{ + put(null, new HashSet() {{ + add("Tom"); + add("Jerry"); + add(null); + }}); + }}; + + public static Map> transformMap(Map input) { + Map> resultMap = new HashMap<>(); + for (Map.Entry entry : input.entrySet()) { + if (!resultMap.containsKey(entry.getValue())) { + resultMap.put(entry.getValue(), new HashSet<>()); + } + resultMap.get(entry.getValue()) + .add(entry.getKey()); + } + return resultMap; + } + + @Test + void whenUsingClassicLoopBasedSolution_thenGetExpectedResult() { + Map> result = transformMap(INPUT_MAP); + assertEquals(EXPECTED, result); + + Map> result2 = transformMap(INPUT_MAP_WITH_NULLS); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingJava8StreamGroupingBy_thenGetExpectedResult() { + Map> result = INPUT_MAP.entrySet() + .stream() + .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet()))); + assertEquals(EXPECTED, result); + + assertThrows(NullPointerException.class, () -> INPUT_MAP_WITH_NULLS.entrySet() + .stream() + .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet())))); + } + + @Test + void whenUsingJava8ForEach_thenGetExpectedResult() { + Map> result = new HashMap<>(); + INPUT_MAP.forEach((key, value) -> result.computeIfAbsent(value, k -> new HashSet<>()) + .add(key)); + assertEquals(EXPECTED, result); + + Map> result2 = new HashMap<>(); + INPUT_MAP_WITH_NULLS.forEach((key, value) -> result2.computeIfAbsent(value, k -> new HashSet<>()) + .add(key)); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingGuavaMultiMapCollector_thenGetExpectedResult() { + Map> result = INPUT_MAP.entrySet() + .stream() + .collect(collectingAndThen(Multimaps.toMultimap(Map.Entry::getValue, Map.Entry::getKey, HashMultimap::create), Multimaps::asMap)); + assertEquals(EXPECTED, result); + + Map> result2 = INPUT_MAP_WITH_NULLS.entrySet() + .stream() + .collect(collectingAndThen(Multimaps.toMultimap(Map.Entry::getValue, Map.Entry::getKey, HashMultimap::create), Multimaps::asMap)); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + + @Test + void whenUsingGuavaInvertFromAndForMap_thenGetExpectedResult() { + SetMultimap multiMap = Multimaps.invertFrom(Multimaps.forMap(INPUT_MAP), HashMultimap.create()); + Map> result = Multimaps.asMap(multiMap); + assertEquals(EXPECTED, result); + + SetMultimap multiMapWithNulls = Multimaps.invertFrom(Multimaps.forMap(INPUT_MAP_WITH_NULLS), HashMultimap.create()); + Map> result2 = Multimaps.asMap(multiMapWithNulls); + assertEquals(EXPECTED_WITH_NULLS, result2); + } + +} \ No newline at end of file diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 85df51457c..bd7aae6410 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -99,6 +99,7 @@ core-java-collections-maps-2 core-java-collections-maps-3 core-java-collections-maps-7 + core-java-collections-maps-8 core-java-compiler core-java-concurrency-2 core-java-concurrency-advanced From a411fd056157c36af1ab470ab8300b7d7d7d95da Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Mon, 25 Mar 2024 12:28:05 +0000 Subject: [PATCH 13/92] https://jira.baeldung.com/browse/BAEL-7667 --- apache-libraries-2/data/inbox/welcome.txt | 1 + apache-libraries-2/data/json/name.json | 4 +++ apache-libraries-2/data/outbox/welcome.txt | 1 + apache-libraries-2/data/output/name.json | 1 + apache-libraries-2/pom.xml | 7 +++-- .../CamelLoggingMainApp.java | 13 +++++++++ .../FileCopierCamelRoute.java | 27 +++++++++++++++++++ .../FileCopierTracerCamelRoute.java | 23 ++++++++++++++++ .../apachecamellogging/FileProcessor.java | 23 ++++++++++++++++ .../DynamicRouterRouteUnitTest.java | 2 +- 10 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 apache-libraries-2/data/inbox/welcome.txt create mode 100644 apache-libraries-2/data/json/name.json create mode 100644 apache-libraries-2/data/outbox/welcome.txt create mode 100644 apache-libraries-2/data/output/name.json create mode 100644 apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java create mode 100644 apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java create mode 100644 apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java create mode 100644 apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java rename apache-libraries-2/src/test/java/{ => com/baeldung}/dynamicrouter/DynamicRouterRouteUnitTest.java (98%) diff --git a/apache-libraries-2/data/inbox/welcome.txt b/apache-libraries-2/data/inbox/welcome.txt new file mode 100644 index 0000000000..9f55d12685 --- /dev/null +++ b/apache-libraries-2/data/inbox/welcome.txt @@ -0,0 +1 @@ +Welcome to Baeldung \ No newline at end of file diff --git a/apache-libraries-2/data/json/name.json b/apache-libraries-2/data/json/name.json new file mode 100644 index 0000000000..1f7e064a56 --- /dev/null +++ b/apache-libraries-2/data/json/name.json @@ -0,0 +1,4 @@ +{ + "name" : "phillip", + "age" : 5 +} \ No newline at end of file diff --git a/apache-libraries-2/data/outbox/welcome.txt b/apache-libraries-2/data/outbox/welcome.txt new file mode 100644 index 0000000000..c4c82085cb --- /dev/null +++ b/apache-libraries-2/data/outbox/welcome.txt @@ -0,0 +1 @@ +WELCOME TO BAELDUNG \ No newline at end of file diff --git a/apache-libraries-2/data/output/name.json b/apache-libraries-2/data/output/name.json new file mode 100644 index 0000000000..d075754d1b --- /dev/null +++ b/apache-libraries-2/data/output/name.json @@ -0,0 +1 @@ +{"name":"phillip","age":5,"transformedName":"PHILLIP","transformedAge":15} \ No newline at end of file diff --git a/apache-libraries-2/pom.xml b/apache-libraries-2/pom.xml index 2e7ef0344c..7ad70d8978 100644 --- a/apache-libraries-2/pom.xml +++ b/apache-libraries-2/pom.xml @@ -24,19 +24,22 @@ camel-core ${camel.version} - org.apache.camel camel-test-junit5 ${camel.version} test - org.apache.camel camel-main ${camel.version} + + org.apache.camel + camel-jackson + ${camel.version} + diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java new file mode 100644 index 0000000000..c4b9b998ab --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java @@ -0,0 +1,13 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.main.Main; + +public class CamelLoggingMainApp { + + public static void main(String[] args) throws Exception { + Main main = new Main(); + main.configure() + .addRoutesBuilder(new FileCopierTracerCamelRoute()); + main.run(args); + } +} diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java new file mode 100644 index 0000000000..c8b52b4e6f --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java @@ -0,0 +1,27 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileCopierCamelRoute extends RouteBuilder { + + private static Logger logger = LoggerFactory.getLogger(FileCopierCamelRoute.class); + + public void configure() { + from("file:data/inbox?noop=true").log("We got an incoming file ${file:name} containing: ${body}") + .to("log:com.baeldung.apachecamellogging?level=INFO") + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + logger.info("We are passing the message to a FileProcesor to Capitalize the message body"); + } + }) + .bean(FileProcessor.class) + .to("file:data/outbox") + .log("Successlly transfer file: ${file:name}"); + } +} \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java new file mode 100644 index 0000000000..666feac7ec --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java @@ -0,0 +1,23 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.dataformat.JsonLibrary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileCopierTracerCamelRoute extends RouteBuilder { + + Logger logger = LoggerFactory.getLogger(FileCopierTracerCamelRoute.class); + + public void configure() { + getContext().setTracing(true); + from("file:data/json?noop=true").to("log:input?level=INFO") + .unmarshal() + .json(JsonLibrary.Jackson) + .bean(FileProcessor.class, "transform") + .marshal() + .json(JsonLibrary.Jackson) + .to("file:data/output"); + ; + } +} \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java new file mode 100644 index 0000000000..478fb0ced0 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileProcessor.java @@ -0,0 +1,23 @@ +package com.baeldung.apachecamellogging; + +import org.apache.camel.Body; + +import java.util.Map; + +public class FileProcessor { + + public String process(@Body String fileContent) { + String processedContent = fileContent.toUpperCase(); + return processedContent; + } + + public Map transform(Map input) { + String name = (String) input.get("name"); + int age = (int) input.get("age"); + + input.put("transformedName", name.toUpperCase()); + input.put("transformedAge", age + 10); + + return input; + } +} diff --git a/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java b/apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java similarity index 98% rename from apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java rename to apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java index 6401fa4be2..4b93d40dac 100644 --- a/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java +++ b/apache-libraries-2/src/test/java/com/baeldung/dynamicrouter/DynamicRouterRouteUnitTest.java @@ -1,4 +1,4 @@ -package dynamicrouter; +package com.baeldung.dynamicrouter; import com.baeldung.dynamicrouter.DynamicRouterRoute; import org.apache.camel.RoutesBuilder; From 2e2ac76b455428c851b4e606022b48f8eb244183 Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Tue, 26 Mar 2024 12:28:14 +0000 Subject: [PATCH 14/92] https://jira.baeldung.com/browse/BAEL-7667 --- apache-libraries-2/pom.xml | 2 +- .../apachecamellogging/CamelLoggingMainApp.java | 2 +- .../apachecamellogging/FileCopierCamelRoute.java | 15 +++++++-------- .../FileCopierTracerCamelRoute.java | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/apache-libraries-2/pom.xml b/apache-libraries-2/pom.xml index 7ad70d8978..b1e1a47d5f 100644 --- a/apache-libraries-2/pom.xml +++ b/apache-libraries-2/pom.xml @@ -44,7 +44,7 @@ 2.0.1.Final - 4.3.0 + 4.4.1 \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java index c4b9b998ab..8eaad95959 100644 --- a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/CamelLoggingMainApp.java @@ -7,7 +7,7 @@ public class CamelLoggingMainApp { public static void main(String[] args) throws Exception { Main main = new Main(); main.configure() - .addRoutesBuilder(new FileCopierTracerCamelRoute()); + .addRoutesBuilder(new FileCopierCamelRoute()); main.run(args); } } diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java index c8b52b4e6f..879843e397 100644 --- a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java @@ -1,7 +1,6 @@ package com.baeldung.apachecamellogging; -import org.apache.camel.Exchange; -import org.apache.camel.Processor; +import org.apache.camel.LoggingLevel; import org.apache.camel.builder.RouteBuilder; import org.slf4j.Logger; @@ -9,19 +8,19 @@ import org.slf4j.LoggerFactory; public class FileCopierCamelRoute extends RouteBuilder { - private static Logger logger = LoggerFactory.getLogger(FileCopierCamelRoute.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FileCopierCamelRoute.class); public void configure() { from("file:data/inbox?noop=true").log("We got an incoming file ${file:name} containing: ${body}") .to("log:com.baeldung.apachecamellogging?level=INFO") - .process(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - logger.info("We are passing the message to a FileProcesor to Capitalize the message body"); - } + + .process(process -> { + LOGGER.info("We are passing the message to a FileProcesor bean to capitalize the message body"); }) .bean(FileProcessor.class) .to("file:data/outbox") + .to("log:com.baeldung.apachecamellogging?showBodyType=false&maxChars=20") + .log(LoggingLevel.DEBUG, "Output Process", "The Process ${id}") .log("Successlly transfer file: ${file:name}"); } } \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java index 666feac7ec..fea144ce66 100644 --- a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierTracerCamelRoute.java @@ -18,6 +18,5 @@ public class FileCopierTracerCamelRoute extends RouteBuilder { .marshal() .json(JsonLibrary.Jackson) .to("file:data/output"); - ; } } \ No newline at end of file From 98fcb6edefa15e3ffda8c5649f324b76386334bf Mon Sep 17 00:00:00 2001 From: balasr3 Date: Tue, 26 Mar 2024 23:43:48 +0000 Subject: [PATCH 15/92] BAEL-7593: added implementation and test for kafka delayed message consumption --- spring-kafka-3/pom.xml | 12 ++ .../delay/DelayedMessageListenerAdapter.java | 93 ++++++++++++++ .../kafka/delay/KafkaConsumerConfig.java | 64 ++++++++++ .../kafka/delay/KafkaDelayApplication.java | 13 ++ .../baeldung/spring/kafka/delay/Order.java | 27 ++++ .../spring/kafka/delay/OrderListener.java | 37 ++++++ .../spring/kafka/delay/OrderService.java | 31 +++++ .../delay/KafkaDelayIntegrationTest.java | 116 ++++++++++++++++++ 8 files changed, 393 insertions(+) create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java create mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java create mode 100644 spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java diff --git a/spring-kafka-3/pom.xml b/spring-kafka-3/pom.xml index 894eab2576..2d6def9c2c 100644 --- a/spring-kafka-3/pom.xml +++ b/spring-kafka-3/pom.xml @@ -22,6 +22,7 @@ org.springframework.kafka spring-kafka + 2.9.13 com.fasterxml.jackson.core @@ -50,6 +51,16 @@ ${awaitility.version} test + + org.projectlombok + lombok + ${lombok.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-datatype.version} + @@ -57,5 +68,6 @@ 3.0.12 1.19.3 4.2.0 + 2.13.5 diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java new file mode 100644 index 0000000000..339f18677a --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java @@ -0,0 +1,93 @@ +package com.baeldung.spring.kafka.delay; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.TopicPartition; +import org.springframework.kafka.listener.AcknowledgingConsumerAwareMessageListener; +import org.springframework.kafka.listener.KafkaBackoffException; +import org.springframework.kafka.listener.KafkaConsumerBackoffManager; +import org.springframework.kafka.listener.MessageListener; +import org.springframework.kafka.listener.adapter.AbstractDelegatingMessageListenerAdapter; +import org.springframework.kafka.support.Acknowledgment; + +public class DelayedMessageListenerAdapter extends AbstractDelegatingMessageListenerAdapter> implements AcknowledgingConsumerAwareMessageListener { + + private static final Duration DEFAULT_DELAY_VALUE = Duration.of(0, ChronoUnit.SECONDS); + + private final String listenerId; + + private final KafkaConsumerBackoffManager kafkaConsumerBackoffManager; + + private final Map delaysPerTopic = new ConcurrentHashMap<>(); + + private Duration defaultDelay = DEFAULT_DELAY_VALUE; + + public DelayedMessageListenerAdapter(MessageListener delegate, KafkaConsumerBackoffManager kafkaConsumerBackoffManager, String listenerId) { + super(delegate); + Objects.requireNonNull(kafkaConsumerBackoffManager, "kafkaConsumerBackoffManager cannot be null"); + Objects.requireNonNull(listenerId, "listenerId cannot be null"); + this.kafkaConsumerBackoffManager = kafkaConsumerBackoffManager; + this.listenerId = listenerId; + } + + @Override + public void onMessage(ConsumerRecord consumerRecord, Acknowledgment acknowledgment, Consumer consumer) throws KafkaBackoffException { + this.kafkaConsumerBackoffManager.backOffIfNecessary(createContext(consumerRecord, consumerRecord.timestamp() + delaysPerTopic.getOrDefault(consumerRecord.topic(), this.defaultDelay) + .toMillis(), consumer)); + invokeDelegateOnMessage(consumerRecord, acknowledgment, consumer); + } + + public void setDelayForTopic(String topic, Duration delay) { + Objects.requireNonNull(topic, "Topic cannot be null"); + Objects.requireNonNull(delay, "Delay cannot be null"); + this.logger.debug(() -> String.format("Setting delay %s for listener id %s", delay, this.listenerId)); + this.delaysPerTopic.put(topic, delay); + } + + public void setDefaultDelay(Duration delay) { + Objects.requireNonNull(delay, "Delay cannot be null"); + this.logger.debug(() -> String.format("Setting delay %s for listener id %s", delay, this.listenerId)); + this.defaultDelay = delay; + } + + private void invokeDelegateOnMessage(ConsumerRecord consumerRecord, Acknowledgment acknowledgment, Consumer consumer) { + switch (this.delegateType) { + case ACKNOWLEDGING_CONSUMER_AWARE: + this.delegate.onMessage(consumerRecord, acknowledgment, consumer); + break; + case ACKNOWLEDGING: + this.delegate.onMessage(consumerRecord, acknowledgment); + break; + case CONSUMER_AWARE: + this.delegate.onMessage(consumerRecord, consumer); + break; + case SIMPLE: + this.delegate.onMessage(consumerRecord); + } + } + + private KafkaConsumerBackoffManager.Context createContext(ConsumerRecord data, long nextExecutionTimestamp, Consumer consumer) { + return this.kafkaConsumerBackoffManager.createContext(nextExecutionTimestamp, this.listenerId, new TopicPartition(data.topic(), data.partition()), consumer); + } + + @Override + public void onMessage(ConsumerRecord data) { + onMessage(data, null, null); + } + + @Override + public void onMessage(ConsumerRecord data, Acknowledgment acknowledgment) { + onMessage(data, acknowledgment, null); + } + + @Override + public void onMessage(ConsumerRecord data, Consumer consumer) { + onMessage(data, null, consumer); + } +} \ No newline at end of file diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java new file mode 100644 index 0000000000..f84b7d3f2a --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java @@ -0,0 +1,64 @@ +package com.baeldung.spring.kafka.delay; + +import java.time.Duration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; +import org.springframework.kafka.listener.ContainerPartitionPausingBackOffManager; +import org.springframework.kafka.listener.ContainerPausingBackOffHandler; +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaConsumerBackoffManager; +import org.springframework.kafka.listener.ListenerContainerPauseService; +import org.springframework.kafka.listener.ListenerContainerRegistry; +import org.springframework.kafka.listener.MessageListener; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +@Configuration +public class KafkaConsumerConfig { + + @Bean + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(ConsumerFactory consumerFactory, ListenerContainerRegistry registry, TaskScheduler scheduler) { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory); + KafkaConsumerBackoffManager backOffManager = createBackOffManager(registry, scheduler); + factory.getContainerProperties() + .setAckMode(ContainerProperties.AckMode.RECORD); + factory.setContainerCustomizer(container -> { + DelayedMessageListenerAdapter delayedAdapter = wrapWithDelayedMessageListenerAdapter(backOffManager, container); + delayedAdapter.setDelayForTopic("web.orders", Duration.ofSeconds(10)); + delayedAdapter.setDefaultDelay(Duration.ZERO); + container.setupMessageListener(delayedAdapter); + }); + return factory; + } + + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper().registerModule(new JavaTimeModule()) + .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false); + } + + @Bean + public TaskScheduler taskScheduler() { + return new ThreadPoolTaskScheduler(); + } + + @SuppressWarnings("unchecked") + private DelayedMessageListenerAdapter wrapWithDelayedMessageListenerAdapter(KafkaConsumerBackoffManager backOffManager, ConcurrentMessageListenerContainer container) { + return new DelayedMessageListenerAdapter<>((MessageListener) container.getContainerProperties() + .getMessageListener(), backOffManager, container.getListenerId()); + } + + private ContainerPartitionPausingBackOffManager createBackOffManager(ListenerContainerRegistry registry, TaskScheduler scheduler) { + return new ContainerPartitionPausingBackOffManager(registry, new ContainerPausingBackOffHandler(new ListenerContainerPauseService(registry, scheduler))); + } + +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java new file mode 100644 index 0000000000..6303c045bc --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.kafka.delay; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.kafka.annotation.EnableKafka; + +@EnableKafka +@SpringBootApplication +public class KafkaDelayApplication { + public static void main(String[] args) { + SpringApplication.run(KafkaDelayApplication.class, args); + } +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java new file mode 100644 index 0000000000..e781e76466 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.kafka.delay; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Order { + + private UUID orderId; + + private LocalDateTime orderGeneratedDateTime; + + private LocalDateTime orderProcessedTime; + + private List address; + + private double price; +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java new file mode 100644 index 0000000000..3c5c4a69e5 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java @@ -0,0 +1,37 @@ +package com.baeldung.spring.kafka.delay; + +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.annotation.RetryableTopic; +import org.springframework.kafka.listener.KafkaBackoffException; +import org.springframework.kafka.retrytopic.DltStrategy; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import groovy.util.logging.Slf4j; + +@Slf4j +@Component +public class OrderListener { + + private final OrderService orderService; + + private final ObjectMapper objectMapper; + + public OrderListener(OrderService orderService, ObjectMapper objectMapper) { + this.orderService = orderService; + this.objectMapper = objectMapper; + } + + @RetryableTopic(attempts = "1", include = KafkaBackoffException.class, dltStrategy = DltStrategy.NO_DLT) + @KafkaListener(topics = { "web.orders", "web.internal.orders" }, groupId = "orders") + public void handleOrders(String order) throws JsonProcessingException { + Order orderDetails = objectMapper.readValue(order, Order.class); + OrderService.Status orderStatus = orderService.findStatusById(orderDetails.getOrderId()); + if (orderStatus.equals(OrderService.Status.ORDER_CONFIRMED)) { + orderService.processOrder(orderDetails); + } + } + +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java new file mode 100644 index 0000000000..f91e67c1d1 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java @@ -0,0 +1,31 @@ +package com.baeldung.spring.kafka.delay; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Service; + +@Service +public class OrderService { + + HashMap orders = new HashMap<>(); + + public Status findStatusById(UUID orderId) { + return Status.ORDER_CONFIRMED; + } + + public void processOrder(Order order) { + order.setOrderProcessedTime(LocalDateTime.now()); + orders.put(order.getOrderId(), order); + } + + public Map getOrders() { + return orders; + } + + enum Status { + CREATED, ORDER_CONFIRMED, ORDER_PROCESSED, DELETED + } +} diff --git a/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java b/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java new file mode 100644 index 0000000000..8264e67bb2 --- /dev/null +++ b/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java @@ -0,0 +1,116 @@ +package com.baeldung.spring.kafka.delay; + +import static org.awaitility.Awaitility.await; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +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.serialization.StringSerializer; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +@Testcontainers +@SpringBootTest(classes = KafkaDelayApplication.class) +class KafkaDelayIntegrationTest { + + @Container + private static KafkaContainer KAFKA = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")); + private static KafkaProducer testKafkaProducer; + private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()) + .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + + @Autowired + OrderService orderService; + + @DynamicPropertySource + static void setProps(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", KAFKA::getBootstrapServers); + } + + @BeforeAll + static void beforeAll() { + Properties props = new Properties(); + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA.getBootstrapServers()); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + testKafkaProducer = new KafkaProducer<>(props); + } + + @Test + void givenKafkaBrokerExists_whenCreteOrderIsReceived_thenMessageShouldBeDelayed() throws Exception { + // Given + var orderId = UUID.randomUUID(); + Order order = Order.builder() + .orderId(orderId) + .price(1.0) + .orderGeneratedDateTime(LocalDateTime.now()) + .address(List.of("41 Felix Avenue, Luton")) + .build(); + + String orderString = objectMapper.writeValueAsString(order); + ProducerRecord record = new ProducerRecord<>("web.orders", orderString); + // When + testKafkaProducer.send(record) + .get(); + await().atMost(Duration.ofSeconds(1800)) + .until(() -> { + // then + Map orders = orderService.getOrders(); + return orders != null && orders.get(orderId) != null && Duration.between(orders.get(orderId) + .getOrderGeneratedDateTime(), orders.get(orderId) + .getOrderProcessedTime()) + .getSeconds() >= 10; + }); + } + + @Test + void givenKafkaBrokerExists_whenCreteOrderIsReceivedForOtherTopics_thenMessageShouldNotBeDelayed() throws Exception { + // Given + var orderId = UUID.randomUUID(); + Order order = Order.builder() + .orderId(orderId) + .price(1.0) + .orderGeneratedDateTime(LocalDateTime.now()) + .address(List.of("41 Felix Avenue, Luton")) + .build(); + + String orderString = objectMapper.writeValueAsString(order); + ProducerRecord record = new ProducerRecord<>("web.internal.orders", orderString); + // When + testKafkaProducer.send(record) + .get(); + await().atMost(Duration.ofSeconds(1800)) + .until(() -> { + // Then + Map orders = orderService.getOrders(); + System.out.println("Time...." + Duration.between(orders.get(orderId) + .getOrderGeneratedDateTime(), orders.get(orderId) + .getOrderProcessedTime()) + .getSeconds()); + return orders != null && orders.get(orderId) != null && Duration.between(orders.get(orderId) + .getOrderGeneratedDateTime(), orders.get(orderId) + .getOrderProcessedTime()) + .getSeconds() <= 1; + }); + } + +} \ No newline at end of file From e9ba1e73ff1b19b4eb95f2201e56c088226c8fb7 Mon Sep 17 00:00:00 2001 From: Zeeshan Arif Date: Wed, 27 Mar 2024 05:39:30 +0500 Subject: [PATCH 16/92] Code added for ticket: BAEL-7621: StructDepartment.java StructManager.java - (contains the @Struct annotation which is the annotation the ticket is about. HibernateStructUnitTest.java - Struct unit test class. No unit test present because the hibernate dialect: org.hibernate.dialect.DerbyDialect does not support the @Struct annotation despite the fact that Apache Derby has support for CREATE TYPE (https://db.apache.org/derby/docs/10.17/ref/rrefsqljcreatetype.html) ddls. hibernate-derby.properties - properties file, just for reference, not being used in unit tests. --- .../struct/entities/StructDepartment.java | 51 +++++++++ .../struct/entities/StructManager.java | 52 +++++++++ .../struct/HibernateStructUnitTest.java | 101 ++++++++++++++++++ .../test/resources/hibernate-derby.properties | 17 +++ 4 files changed, 221 insertions(+) create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java create mode 100644 persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java create mode 100644 persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java new file mode 100644 index 0000000000..419c47791a --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructDepartment.java @@ -0,0 +1,51 @@ +package com.baeldung.hibernate.struct.entities; + +import jakarta.persistence.*; + +@Entity +public class StructDepartment { + @Id + @GeneratedValue + private Integer id; + + @Column + private String departmentName; + + @Embedded + @Column + private StructManager manager; + + @Override + public String toString() { + return "Department{" + + "id=" + id + + ", departmentName='" + departmentName + '\'' + + ", manager=" + manager + + '}'; + } + + public StructDepartment(String departmentName, StructManager manager) { + this.departmentName = departmentName; + this.manager = manager; + } + + public Integer getId() { + return id; + } + + public String getDepartmentName() { + return departmentName; + } + + public void setDepartmentName(String departmentName) { + this.departmentName = departmentName; + } + + public StructManager getManager() { + return manager; + } + + public void setManager(StructManager manager) { + this.manager = manager; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java new file mode 100644 index 0000000000..10595ecc55 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/struct/entities/StructManager.java @@ -0,0 +1,52 @@ +package com.baeldung.hibernate.struct.entities; +import jakarta.persistence.Embeddable; +import org.hibernate.annotations.Struct; + +import java.io.Serializable; + +@Embeddable +@Struct(name = "Department_Manager_Type", attributes = {"firstName", "lastName", "qualification"}) +public class StructManager implements Serializable { + private String firstName; + private String lastName; + private String qualification; + + @Override + public String toString() { + return "Manager{" + + "firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", qualification='" + qualification + '\'' + + '}'; + } + + public StructManager(String firstName, String lastName, String qualification) { + this.firstName = firstName; + this.lastName = lastName; + this.qualification = qualification; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getQualification() { + return qualification; + } + + public void setQualification(String qualification) { + this.qualification = qualification; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java new file mode 100644 index 0000000000..a836fe0de1 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/struct/HibernateStructUnitTest.java @@ -0,0 +1,101 @@ +package com.baeldung.hibernate.struct; + +import com.baeldung.hibernate.struct.entities.StructDepartment; +import com.baeldung.hibernate.struct.entities.StructManager; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateStructUnitTest { + + private Session session; + private Transaction transaction; + + public static SessionFactory getSessionFactoryByProperties(Properties properties) throws IOException { + ServiceRegistry serviceRegistry = configureServiceRegistry(properties); + return makeSessionFactory(serviceRegistry); + } + + private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addPackage("com.baeldung.hibernate.struct.entities"); + metadataSources.addAnnotatedClass(StructDepartment.class); + metadataSources.addAnnotatedClass(StructManager.class); + + Metadata metadata = metadataSources.getMetadataBuilder() + .build(); + + return metadata.getSessionFactoryBuilder() + .build(); + + } + private static ServiceRegistry configureServiceRegistry(Properties properties) throws IOException { + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + public static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate-derby.properties")); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } + + private static ServiceRegistry configureServiceRegistry() throws IOException { + return configureServiceRegistry(getProperties()); + } + private static String PROPERTY_FILE_NAME; + public static SessionFactory getSessionFactory(String propertyFileName) throws IOException { + PROPERTY_FILE_NAME = propertyFileName; + ServiceRegistry serviceRegistry = configureServiceRegistry(); + return makeSessionFactory(serviceRegistry); + } + @Before + public void setUp() throws IOException { + session = getSessionFactory("hibernate-derby.properties") + .openSession(); + transaction = session.beginTransaction(); + + transaction.commit(); + transaction = session.beginTransaction(); + } + + @After + public void tearDown() { + transaction.rollback(); + session.close(); + } + + + +/* This unit test is for reference only because the Hibernate dialect for + Apache Derby database does not support @Struct annotation. + + @Test + public void givenSaveDepartmentObject_ThenManagerUDTExists() { + StructDepartment d = new StructDepartment("Information Technology" + , new StructManager("Zeeshan", "Arif", "Qualified")); + + session.persist(d); + session.flush(); + session.clear(); + + }*/ +} diff --git a/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties new file mode 100644 index 0000000000..72256d1687 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/test/resources/hibernate-derby.properties @@ -0,0 +1,17 @@ +hibernate.connection.driver_class=org.apache.derby.jdbc.EmbeddedDriver +hibernate.connection.url=jdbc:derby:db/derby.dbfile;create=true +hibernate.connection.username= +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.DerbyDialect + +# enable to see Hibernate generated SQL +hibernate.show_sql=false + +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 From 5c18b2e7f7b84daae9dc4687ca11238afacd67ed Mon Sep 17 00:00:00 2001 From: Tetiana Okhotnik Date: Sun, 3 Mar 2024 23:35:32 +0200 Subject: [PATCH 17/92] BAEL-7238 Inject mock into Spy object in Mockito - added "library" service to demonstrate mockito injection features - updated mockito version to 5.10 --- testing-modules/mockito-2/pom.xml | 9 +++- .../com/baeldung/injectmockintospy/Book.java | 21 +++++++++ .../injectmockintospy/BookControlService.java | 33 +++++++++++++ .../injectmockintospy/BookStorageService.java | 28 +++++++++++ .../injectmockintospy/RepairService.java | 12 +++++ .../injectmockintospy/StatisticService.java | 22 +++++++++ ...MockAndManualSpyWithExtensionUnitTest.java | 32 +++++++++++++ ...MockAndManualSpyWithOpenMocksUnitTest.java | 46 +++++++++++++++++++ ...tMockAndMockitoSpyDoesnotWorkUnitTest.java | 36 +++++++++++++++ ...ngleInjectMockAndAnnotatedSpyUnitTest.java | 33 +++++++++++++ ...ockAndManualSpyWithReflectionUnitTest.java | 46 +++++++++++++++++++ 11 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/Book.java create mode 100644 testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookControlService.java create mode 100644 testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookStorageService.java create mode 100644 testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/RepairService.java create mode 100644 testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/StatisticService.java create mode 100644 testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithExtensionUnitTest.java create mode 100644 testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithOpenMocksUnitTest.java create mode 100644 testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndMockitoSpyDoesnotWorkUnitTest.java create mode 100644 testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndAnnotatedSpyUnitTest.java create mode 100644 testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndManualSpyWithReflectionUnitTest.java diff --git a/testing-modules/mockito-2/pom.xml b/testing-modules/mockito-2/pom.xml index 9e9d208266..79b8c86221 100644 --- a/testing-modules/mockito-2/pom.xml +++ b/testing-modules/mockito-2/pom.xml @@ -24,11 +24,18 @@ ${mockito.version} test + + org.projectlombok + lombok + ${lombok.version} + compile + 4.8.1 - 5.9.0 + 5.10.0 + 1.18.30 \ No newline at end of file diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/Book.java b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/Book.java new file mode 100644 index 0000000000..0bd06e9ea2 --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/Book.java @@ -0,0 +1,21 @@ +package com.baeldung.injectmockintospy; + +import java.time.ZonedDateTime; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Book { + private String name; + private String author; + private long timesTaken; + private ZonedDateTime returnDate; + + public Book(String name, String author, long timesTaken) { + this.name = name; + this.author = author; + this.timesTaken = timesTaken; + } +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookControlService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookControlService.java new file mode 100644 index 0000000000..1ccdde329e --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookControlService.java @@ -0,0 +1,33 @@ +package com.baeldung.injectmockintospy; + +import java.time.ZonedDateTime; + +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@NoArgsConstructor +public class BookControlService { + + private StatisticService statisticService; + private RepairService repairService; + + public void returnBook(Book book) { + book.setReturnDate(null); + statisticService.calculateAdded(); + if(repairService.shouldRepair(book)){ + log.info("Book should be repaired"); + } + } + + public void giveBook(Book book) { + book.setReturnDate(ZonedDateTime.now().plusDays(14L)); + statisticService.calculateRemoved(); + } + + public BookControlService(StatisticService statisticService, RepairService repairService) { + this.statisticService = statisticService; + this.repairService = repairService; + } + +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookStorageService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookStorageService.java new file mode 100644 index 0000000000..993b54b33b --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/BookStorageService.java @@ -0,0 +1,28 @@ +package com.baeldung.injectmockintospy; + +import java.util.LinkedList; +import java.util.List; + +import lombok.Getter; + +@Getter +public class BookStorageService { + + private BookControlService bookControlService; + private final List availableBooks = new LinkedList<>(); + + public BookStorageService(BookControlService bookControlService) { + this.bookControlService = bookControlService; + } + + public void returnBook(Book book) { + availableBooks.add(book); + bookControlService.returnBook(book); + } + + public void giveBook(Book book) { + availableBooks.remove(book); + bookControlService.giveBook(book); + } + +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/RepairService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/RepairService.java new file mode 100644 index 0000000000..254b26d7dd --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/RepairService.java @@ -0,0 +1,12 @@ +package com.baeldung.injectmockintospy; + +import lombok.Getter; + +@Getter +public class RepairService { + + public boolean shouldRepair(Book book) { + return book.getTimesTaken() > 10; + } + +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/StatisticService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/StatisticService.java new file mode 100644 index 0000000000..e35a7054e9 --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/injectmockintospy/StatisticService.java @@ -0,0 +1,22 @@ +package com.baeldung.injectmockintospy; + +import lombok.Getter; + +@Getter +public class StatisticService { + + private long todaysActions; + + public void calculateAdded() { + todaysActions++; + } + + public void calculateRemoved() { + todaysActions--; + } + + public void reset() { + todaysActions = 0L; + } + +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithExtensionUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithExtensionUnitTest.java new file mode 100644 index 0000000000..8ff6ea9fe0 --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithExtensionUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.injectmockintospy; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MultipleInjectMockAndManualSpyWithExtensionUnitTest { + @InjectMocks + private BookStorageService bookStorageService; + @InjectMocks + private BookControlService bookControlService = Mockito.spy(BookControlService.class); + @Mock + private StatisticService statisticService; + @Mock + private RepairService repairService; + + @Test + void whenInjectMockUsedWithManualSpy_thenMockitoCanInjectMocks() { + Book book = new Book("Some name", "Some author", 355); + bookStorageService.returnBook(book); + + Assertions.assertEquals(1, bookStorageService.getAvailableBooks().size()); + Mockito.verify(bookControlService).returnBook(book); + Mockito.verify(statisticService).calculateAdded(); + Mockito.verify(repairService).shouldRepair(book); + } +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithOpenMocksUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithOpenMocksUnitTest.java new file mode 100644 index 0000000000..8e71b84c64 --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndManualSpyWithOpenMocksUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.injectmockintospy; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +public class MultipleInjectMockAndManualSpyWithOpenMocksUnitTest { + + @InjectMocks + private BookStorageService bookStorageService; + @InjectMocks + private BookControlService bookControlService; + @Mock + private StatisticService statisticService; + @Mock + private RepairService repairService; + private AutoCloseable closeable; + + @BeforeEach + public void openMocks() { + bookControlService = Mockito.spy(BookControlService.class); + closeable = MockitoAnnotations.openMocks(this); + } + + @AfterEach + public void releaseMocks() throws Exception { + closeable.close(); + } + + @Test + void whenInjectMockUsedWithManualSpy_thenMockitoCanInjectMocks() { + Book book = new Book("Some name", "Some author", 355); + bookStorageService.returnBook(book); + + Assertions.assertEquals(1, bookStorageService.getAvailableBooks().size()); + + Mockito.verify(bookControlService).returnBook(book); + Mockito.verify(statisticService).calculateAdded(); + Mockito.verify(repairService).shouldRepair(book); + } +} \ No newline at end of file diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndMockitoSpyDoesnotWorkUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndMockitoSpyDoesnotWorkUnitTest.java new file mode 100644 index 0000000000..d522ebf01d --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/MultipleInjectMockAndMockitoSpyDoesnotWorkUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.injectmockintospy; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MultipleInjectMockAndMockitoSpyDoesnotWorkUnitTest { + @InjectMocks + private BookStorageService bookStorageService; + @InjectMocks + @Spy + private BookControlService bookControlService; + @Mock + private StatisticService statisticService; + @Mock + private RepairService repairService; + + @Test + @Disabled("test is not intended to work, it is here to show that such mock setup doesn't work") + void whenInjectMockUsedWithMockitoSpy_thenMockitoCannotInjectObjectProperly() { + Book book = new Book("Some name", "Some author", 355); + bookStorageService.returnBook(book); + + Assertions.assertEquals(1, bookStorageService.getAvailableBooks().size()); + Mockito.verify(bookControlService).returnBook(book); + Mockito.verify(statisticService).calculateAdded(); + Mockito.verify(repairService).shouldRepair(book); + } +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndAnnotatedSpyUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndAnnotatedSpyUnitTest.java new file mode 100644 index 0000000000..abd1075d86 --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndAnnotatedSpyUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.injectmockintospy; + +import java.time.ZonedDateTime; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class SingleInjectMockAndAnnotatedSpyUnitTest { + @Spy + @InjectMocks + private BookControlService bookControlService; + @Mock + private StatisticService statisticService; + @Spy + private RepairService repairService; + + @Test + void whenOneInjectMockWithSpy_thenHierarchySuccessfullyInitialized() { + Book book = new Book("Some name", "Some author", 355, ZonedDateTime.now()); + bookControlService.returnBook(book); + + Assertions.assertNull(book.getReturnDate()); + Mockito.verify(statisticService).calculateAdded(); + Mockito.verify(repairService).shouldRepair(book); + } +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndManualSpyWithReflectionUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndManualSpyWithReflectionUnitTest.java new file mode 100644 index 0000000000..f8e697e7d6 --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/injectmockintospy/SingleInjectMockAndManualSpyWithReflectionUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.injectmockintospy; + +import java.lang.reflect.Field; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class SingleInjectMockAndManualSpyWithReflectionUnitTest { + @InjectMocks + private BookStorageService bookStorageService; + @Mock + private StatisticService statisticService; + @Mock + private RepairService repairService; + private BookControlService bookControlService; + + @BeforeEach + public void openMocks() throws Exception { + bookControlService = Mockito.spy(new BookControlService(statisticService, repairService)); + injectSpyToTestedMock(bookStorageService, bookControlService); + } + + private void injectSpyToTestedMock(BookStorageService bookStorageService, BookControlService bookControlService) throws NoSuchFieldException, IllegalAccessException { + Field bookControlServiceField = BookStorageService.class.getDeclaredField("bookControlService"); + bookControlServiceField.setAccessible(true); + bookControlServiceField.set(bookStorageService, bookControlService); + } + + @Test + void whenManualSpyInjectedToTestesClass_thenHierarchySuccessfullyInitialized() { + Book book = new Book("Some name", "Some author", 355); + bookStorageService.returnBook(book); + + Assertions.assertEquals(1, bookStorageService.getAvailableBooks().size()); + Mockito.verify(bookControlService).returnBook(book); + Mockito.verify(statisticService).calculateAdded(); + Mockito.verify(repairService).shouldRepair(book); + } +} From f6a766d8ef40d4edbd5a8829651b3a8c93d7ceea Mon Sep 17 00:00:00 2001 From: pentakon Date: Thu, 28 Mar 2024 06:41:06 +0200 Subject: [PATCH 18/92] Example code for BAEL-6840: How to scale a BufferedImage in Java? (#16202) --- .../bufferedimageresize/Application.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java diff --git a/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java b/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java new file mode 100644 index 0000000000..5f79a1a90b --- /dev/null +++ b/image-processing/src/main/java/com/baeldung/imageprocessing/bufferedimageresize/Application.java @@ -0,0 +1,24 @@ +package com.baeldung.image; + +import javax.imageio.ImageIO; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.File; + +public class Application { + + public static void main(String[] args) throws Exception { + BufferedImage srcImg = ImageIO.read(new File("src/main/resources/images/sampleImage.jpg")); + float scaleW = 2.0f, scaleH = 2.0f; + int w = srcImg.getWidth() * (int) scaleW; + int h = srcImg.getHeight() * (int) scaleH; + BufferedImage dstImg = new BufferedImage(w, h, srcImg.getType()); + AffineTransform scalingTransform = new AffineTransform(); + scalingTransform.scale(scaleW, scaleH); + AffineTransformOp scaleOp = new AffineTransformOp(scalingTransform, AffineTransformOp.TYPE_BILINEAR); + dstImg = scaleOp.filter(srcImg, dstImg); + ImageIO.write(dstImg, "jpg", new File("src/main/resources/images/resized.jpg")); + } + +} From d1e36a0b4e9d5fe99809e3ea97c3873a1f46057a Mon Sep 17 00:00:00 2001 From: DiegoMarti2 <150871541+DiegoMarti2@users.noreply.github.com> Date: Thu, 28 Mar 2024 06:43:38 +0200 Subject: [PATCH 19/92] baeldung-articles : BAEL-6607 (#16240) Get a Path to a Resource in a Java JAR File. --- .../GetPathToResourceUnitTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java new file mode 100644 index 0000000000..27b3e1535d --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/getpathtoresource/GetPathToResourceUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.getpathtoresource; + +import org.junit.Test; + +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + +import static org.junit.Assert.assertNotNull; + +public class GetPathToResourceUnitTest { + + @Test + public void givenFile_whenClassUsed_thenGetResourcePath() { + URL resourceUrl = GetPathToResourceUnitTest.class.getResource("/sampleText1.txt"); + assertNotNull(resourceUrl); + } + + @Test + public void givenFile_whenClassLoaderUsed_thenGetResourcePath() { + URL resourceUrl = GetPathToResourceUnitTest.class.getClassLoader().getResource("sampleText1.txt"); + assertNotNull(resourceUrl); + } + + @Test + public void givenFile_whenPathUsed_thenGetResourcePath() throws Exception { + Path resourcePath = Paths.get(Objects.requireNonNull(GetPathToResourceUnitTest.class.getResource("/sampleText1.txt")).toURI()); + assertNotNull(resourcePath); + } + +} From 5d38f245cd9941d7c7e929682f2dcc7b36e80985 Mon Sep 17 00:00:00 2001 From: Bhaskar Ghosh Dastidar Date: Thu, 28 Mar 2024 10:52:17 +0530 Subject: [PATCH 20/92] [BAEL-6954] internet address resolution spi (#16245) * [BAEL-6954] internet address resolution spi * [BAEL-6954] internet address resolution spi * [BAEL-6954] internet address resolution spi * [BAEL-6954] internet address resolution spi * [BAEL-6954] internet address resolution spi * [BAEL-6954] internet address resolution spi --- .../com/baeldung/inetspi/InetAddressSPI.java | 44 +++++++++++++++ .../java/com/baeldung/inetspi/Registry.java | 56 +++++++++++++++++++ .../providers/CustomAddressResolverImpl.java | 42 ++++++++++++++ .../inetspi/InetAddressSPIUnitTest.java | 31 ++++++++++ 4 files changed, 173 insertions(+) create mode 100644 core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java create mode 100644 core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java create mode 100644 core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java create mode 100644 core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java new file mode 100644 index 0000000000..0d5f5c486a --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/InetAddressSPI.java @@ -0,0 +1,44 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.stream.Stream; + +import com.baeldung.inetspi.providers.CustomAddressResolverImpl; + +public class InetAddressSPI { + public String usingGetByName(String host) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByName(host); + return inetAddress.getHostAddress(); + } + + public String[] usingGetAllByName(String host) throws UnknownHostException { + InetAddress[] inetAddresses = InetAddress.getAllByName(host); + return Arrays.stream(inetAddresses).map(InetAddress::getHostAddress).toArray(String[]::new); + } + + public String usingGetByIp(byte[] ip) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByAddress(ip); + + return inetAddress.getHostName(); + } + + public String usingGetByIpAndReturnsCannonName(byte[] ip) throws UnknownHostException { + InetAddress inetAddress = InetAddress.getByAddress(ip); + + return inetAddress.getCanonicalHostName(); + } + + public String getHostUsingCustomImpl(byte[] ip) throws UnknownHostException { + + CustomAddressResolverImpl imp = new CustomAddressResolverImpl(); + return imp.get(null).lookupByAddress(ip); + } + + public Stream getIpUsingCustomImpl(String host) throws UnknownHostException { + + CustomAddressResolverImpl imp = new CustomAddressResolverImpl(); + return imp.get(null).lookupByName(host, null); + } +} diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java new file mode 100644 index 0000000000..db15f6a8d4 --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/Registry.java @@ -0,0 +1,56 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Logger; +import java.util.stream.Stream; + +public class Registry { + private final Map> registry; + + private static final Logger LOGGER = Logger.getLogger(Registry.class.getName()); + + public Registry() { + registry = loadMapWithData(); + } + + public Stream getAddressesfromHost(String host) throws UnknownHostException { + LOGGER.info("Performing Forward Lookup for HOST : " + host); + if (!registry.containsKey(host)) { + throw new UnknownHostException("Missing Host information in Resolver"); + } + return registry.get(host) + .stream() + .map(add -> constructInetAddress(host, add)) + .filter(Objects::nonNull); + } + + public String getHostFromAddress(byte[] arr) throws UnknownHostException { + LOGGER.info("Performing Reverse Lookup for Address : " + Arrays.toString(arr)); + for (Map.Entry> entry : registry.entrySet()) { + if (entry.getValue() + .stream() + .anyMatch(ba -> Arrays.equals(ba, arr))) { + return entry.getKey(); + } + } + throw new UnknownHostException("Address Not Found"); + } + + private Map> loadMapWithData() { + return Map.of("baeldung-local.org", List.of(new byte[] { 1, 2, 3, 4 })); + } + + private static InetAddress constructInetAddress(String host, byte[] address) { + try { + return InetAddress.getByAddress(host, address); + } catch (UnknownHostException unknownHostException) { + return null; + } + } + +} diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java new file mode 100644 index 0000000000..0b1849c3f9 --- /dev/null +++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/inetspi/providers/CustomAddressResolverImpl.java @@ -0,0 +1,42 @@ +package com.baeldung.inetspi.providers; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.spi.InetAddressResolver; +import java.net.spi.InetAddressResolverProvider; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Stream; + +import com.baeldung.inetspi.Registry; + +public class CustomAddressResolverImpl extends InetAddressResolverProvider { + + private static Logger LOGGER = Logger.getLogger(CustomAddressResolverImpl.class.getName()); + + private static Registry registry = new Registry(); + + @Override + public InetAddressResolver get(Configuration configuration) { + LOGGER.info("Using Custom Address Resolver :: " + this.name()); + LOGGER.info("Registry initialised"); + return new InetAddressResolver() { + @Override + public Stream lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException { + return registry.getAddressesfromHost(host); + } + + @Override + public String lookupByAddress(byte[] addr) throws UnknownHostException { + return registry.getHostFromAddress(addr); + } + }; + } + + @Override + public String name() { + return "CustomInternetAddressResolverImpl"; + } +} diff --git a/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java b/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java new file mode 100644 index 0000000000..ad8e6f0e54 --- /dev/null +++ b/core-java-modules/core-java-18/src/test/java/com/baeldung/inetspi/InetAddressSPIUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.inetspi; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.stream.Stream; + +import org.junit.Assert; +import org.junit.Test; + +public class InetAddressSPIUnitTest { + @Test + public void givenInetAddress_whenUsingInetAddress_thenPerformResolution() throws UnknownHostException { + InetAddressSPI spi = new InetAddressSPI(); + Assert.assertNotNull(spi.usingGetByName("www.google.com")); + Assert.assertTrue(spi.usingGetAllByName("www.google.com").length > 1); + Assert.assertNotNull(spi.usingGetByIp(InetAddress.getByName("www.google.com") + .getAddress())); + Assert.assertNotNull(spi.usingGetByIpAndReturnsCannonName(InetAddress.getByName("www.google.com") + .getAddress())); + } + + @Test + public void givenCustomInetAddressImplementation_whenUsingInetAddress_thenPerformResolution() throws UnknownHostException { + InetAddressSPI spi = new InetAddressSPI(); + Assert.assertEquals("baeldung-local.org", spi.getHostUsingCustomImpl(new byte[] { 1, 2, 3, 4 })); + Stream response = spi.getIpUsingCustomImpl("baeldung-local.org"); + Assert.assertArrayEquals(new byte[] { 1, 2, 3, 4 }, response.findFirst() + .get() + .getAddress()); + } +} From 40879b52375f00f3c67d6777e143c9a9977a80ea Mon Sep 17 00:00:00 2001 From: MohamedHelmyKassab <137485958+MohamedHelmyKassab@users.noreply.github.com> Date: Thu, 28 Mar 2024 07:34:21 +0200 Subject: [PATCH 21/92] This PR is related to BAEL-6429 (#16250) * This commit is related to BAEL-6429 This commit aims to add a .html file named test. * This commit is related to BAEL-6429 This commit aims to add a test class named "OpenHtmlFilesUnitTest". * Update OpenHtmlFilesUnitTest.java The java.awt.HeadlessException occures, indicating that the current environment lacks a graphical display necessary for the Desktop class to function properly. So i commented the method. --- .../OpenHtmlFilesUnitTest.java | 45 +++++++++++++++++++ .../src/test/resources/test.html | 15 +++++++ 2 files changed, 60 insertions(+) create mode 100644 core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java create mode 100644 core-java-modules/core-java-io-5/src/test/resources/test.html diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java new file mode 100644 index 0000000000..efa58f565b --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/com.baeldung.openhtmlfiles/OpenHtmlFilesUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.openhtmlfiles; + +import org.junit.Test; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.junit.Assert.*; + +public class OpenHtmlFilesUnitTest { + public URL url; + public String absolutePath; + + public OpenHtmlFilesUnitTest() throws URISyntaxException { + url = getClass().getResource("/test.html"); + assert url != null; + File file = new File(url.toURI()); + if (!file.exists()) { + fail(); + } + absolutePath = file.getAbsolutePath(); + } + /* + @Test + public void givenHtmlFile_whenUsingDesktopClass_thenOpenFileInDefaultBrowser() throws IOException { + File htmlFile = new File(absolutePath); + Desktop.getDesktop().browse(htmlFile.toURI()); + assertTrue(true); + } + */ + @Test + public void givenHtmlFile_whenUsingProcessBuilder_thenOpenFileInDefaultBrowser() throws IOException { + ProcessBuilder pb; + if (System.getProperty("os.name").toLowerCase().contains("win")) { + pb = new ProcessBuilder("cmd.exe", "/c", "start", absolutePath); + } else { + pb = new ProcessBuilder("xdg-open", absolutePath); + } + pb.start(); + assertTrue(true); + } +} diff --git a/core-java-modules/core-java-io-5/src/test/resources/test.html b/core-java-modules/core-java-io-5/src/test/resources/test.html new file mode 100644 index 0000000000..5cb2c410eb --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/resources/test.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + +

Hello dear friend

+ + \ No newline at end of file From ffb5023d045eeb08cea618b58c36c3974adfa9a8 Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Thu, 28 Mar 2024 05:37:03 +0000 Subject: [PATCH 22/92] https://jira.baeldung.com/browse/BAEL-7667 --- .../com/baeldung/apachecamellogging/FileCopierCamelRoute.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java index 879843e397..cd09174d54 100644 --- a/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java +++ b/apache-libraries-2/src/main/java/com/baeldung/apachecamellogging/FileCopierCamelRoute.java @@ -13,7 +13,6 @@ public class FileCopierCamelRoute extends RouteBuilder { public void configure() { from("file:data/inbox?noop=true").log("We got an incoming file ${file:name} containing: ${body}") .to("log:com.baeldung.apachecamellogging?level=INFO") - .process(process -> { LOGGER.info("We are passing the message to a FileProcesor bean to capitalize the message body"); }) @@ -21,6 +20,6 @@ public class FileCopierCamelRoute extends RouteBuilder { .to("file:data/outbox") .to("log:com.baeldung.apachecamellogging?showBodyType=false&maxChars=20") .log(LoggingLevel.DEBUG, "Output Process", "The Process ${id}") - .log("Successlly transfer file: ${file:name}"); + .log("Successfully transfer file: ${file:name}"); } } \ No newline at end of file From 4a95314449f2e783c30df8cfd4999f772fea1811 Mon Sep 17 00:00:00 2001 From: "emanuel.trandafir" Date: Thu, 21 Mar 2024 18:07:54 +0100 Subject: [PATCH 23/92] BAEL-7547: testing spring events --- .../application/events/orders/Order.java | 12 ++++++ .../events/orders/OrderCompletedEvent.java | 6 +++ .../events/orders/OrderRepository.java | 25 +++++++++++ .../events/orders/OrderService.java | 29 +++++++++++++ .../rewards/LoyalCustomersRepository.java | 41 +++++++++++++++++++ .../events/rewards/LoyaltyPointsService.java | 28 +++++++++++++ .../events/ApplicationEventsTest.java | 38 +++++++++++++++++ 7 files changed, 179 insertions(+) create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java new file mode 100644 index 0000000000..a0ba6815bc --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java @@ -0,0 +1,12 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.time.Instant; +import java.util.List; + +record Order(String id, String customerId, List productIds, Instant timestamp) { + + public Order(String customerId, List productIds) { + this(null, customerId, productIds, Instant.now()); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java new file mode 100644 index 0000000000..0f11468241 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java @@ -0,0 +1,6 @@ +package com.baeldung.springmodulith.application.events.orders; + +import java.time.Instant; + +public record OrderCompletedEvent(String orderId, String customerId, Instant time) { +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java new file mode 100644 index 0000000000..d02b00d2d0 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java @@ -0,0 +1,25 @@ +package com.baeldung.springmodulith.application.events.orders; + +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Component +class OrderRepository { + private final List orders = new ArrayList<>(); + + public Order save(Order order) { + order = new Order(UUID.randomUUID().toString(), order.customerId(), order.productIds(), order.timestamp()); + orders.add(order); + return order; + } + + public List ordersByCustomer(String customerId) { + return orders.stream() + .filter(it -> it.customerId().equals(customerId)) + .toList(); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java new file mode 100644 index 0000000000..c3b52d478b --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java @@ -0,0 +1,29 @@ +package com.baeldung.springmodulith.application.events.orders; + +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import java.util.Arrays; + +@Service +public class OrderService { + + private final OrderRepository repository; + private final ApplicationEventPublisher eventPublisher; + + public OrderService(OrderRepository orders, ApplicationEventPublisher eventsPublisher) { + this.repository = orders; + this.eventPublisher = eventsPublisher; + } + + public void placeOrder(String customerId, String... productIds) { + Order order = new Order(customerId, Arrays.asList(productIds)); + // business logic to validate and place the order + + Order savedOrder = repository.save(order); + + OrderCompletedEvent event = new OrderCompletedEvent(savedOrder.id(), savedOrder.customerId(), savedOrder.timestamp()); + eventPublisher.publishEvent(event); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java new file mode 100644 index 0000000000..764924232d --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java @@ -0,0 +1,41 @@ +package com.baeldung.springmodulith.application.events.rewards; + +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Component +public class LoyalCustomersRepository { + + private List customers = new ArrayList<>(); + + public Optional find(String customerId) { + return customers.stream() + .filter(it -> it.customerId().equals(customerId)) + .findFirst(); + } + + public void awardPoints(String customerId, int points) { + var customer = find(customerId).orElseThrow(); + customers.remove(customer); + customers.add(customer.addPoints(points)); + } + + public void save(String customerId) { + customers.add(new LoyalCustomer(customerId, 0)); + } + + public boolean isLoyalCustomer(String customerId) { + return find(customerId).isPresent(); + } + + public record LoyalCustomer(String customerId, int points) { + + LoyalCustomer addPoints(int points) { + return new LoyalCustomer(customerId, this.points() + points); + } + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java new file mode 100644 index 0000000000..20af0caa6f --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java @@ -0,0 +1,28 @@ +package com.baeldung.springmodulith.application.events.rewards; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +@Service +public class LoyaltyPointsService { + + public static final int ORDER_COMPLETED_POINTS = 10; + public static final int SING_UP_POINTS = 50; + private final LoyalCustomersRepository loyalCustomers; + + public LoyaltyPointsService(LoyalCustomersRepository loyalCustomers) { + this.loyalCustomers = loyalCustomers; + } + + @EventListener + public void onOrderCompleted(OrderCompletedEvent event) { + if (loyalCustomers.find(event.customerId()).isEmpty()) { + loyalCustomers.save(event.customerId()); + loyalCustomers.awardPoints(event.customerId(), SING_UP_POINTS); + } + + loyalCustomers.awardPoints(event.customerId(), ORDER_COMPLETED_POINTS); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java new file mode 100644 index 0000000000..82fd53d13e --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java @@ -0,0 +1,38 @@ +package com.baeldung.springmodulith.application.events; + +import com.baeldung.springmodulith.application.events.orders.OrderService; +import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; +import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository.LoyalCustomer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") +public class ApplicationEventsTest { + + + @Autowired + OrderService orderService; + + @Autowired + LoyalCustomersRepository loyalCustomers; + + @Test + void whenNewCustomerCompletesAnOrder_thenHeReceivesSingUpPointsPlusOrderPoints() { + orderService.placeOrder("customer1", "product1", "product2"); + + Optional customer = loyalCustomers.find("customer1"); + + assertThat(customer).isPresent() + .get() + .extracting(LoyalCustomer::points) + .isEqualTo(50 + 10); + } + +} From 5e9a5b9b3f19590bcf6698227c4df735414e5c97 Mon Sep 17 00:00:00 2001 From: emanueltrandafir1993 Date: Thu, 21 Mar 2024 23:26:12 +0100 Subject: [PATCH 24/92] BAEL-7574: added tests --- .../events/orders/OrderCompletedEvent.java | 2 +- ...st.java => ApplicationEventsUnitTest.java} | 3 +- .../events/EventListenerUnitTest.java | 39 +++++++++++++++++++ .../events/EventPublisherUnitTest.java | 39 +++++++++++++++++++ .../application/events/TestEventListener.java | 29 ++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) rename spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/{ApplicationEventsTest.java => ApplicationEventsUnitTest.java} (96%) create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java create mode 100644 spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java index 0f11468241..4344b336ac 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderCompletedEvent.java @@ -2,5 +2,5 @@ package com.baeldung.springmodulith.application.events.orders; import java.time.Instant; -public record OrderCompletedEvent(String orderId, String customerId, Instant time) { +public record OrderCompletedEvent(String orderId, String customerId, Instant timestamp) { } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java similarity index 96% rename from spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java rename to spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java index 82fd53d13e..0ebf96b33f 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java @@ -14,8 +14,7 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") -public class ApplicationEventsTest { - +public class ApplicationEventsUnitTest { @Autowired OrderService orderService; diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java new file mode 100644 index 0000000000..b8ad79e6f1 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.springmodulith.application.events; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Instant; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.ComponentScan; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; +import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; + +@SpringBootTest +@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") +public class EventListenerUnitTest { + + @Autowired + private LoyalCustomersRepository customers; + + @Autowired + private ApplicationEventPublisher testEventPublisher; + + @Test + void whenPublishingOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints() { + OrderCompletedEvent event = new OrderCompletedEvent("order-1", "customer-1", Instant.now()); + + testEventPublisher.publishEvent(event); + + assertThat(customers.find("customer-1")) + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java new file mode 100644 index 0000000000..0989bb5fd3 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.springmodulith.application.events; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; + +import com.baeldung.springmodulith.application.events.orders.OrderService; + +@SpringBootTest +@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") +public class EventPublisherUnitTest { + + @Autowired + OrderService orderService; + + @Autowired + TestEventListener testEventListener; + + @BeforeEach + void beforeEach() { + testEventListener.reset(); + } + + @Test + void whenPlacingOrder_thenPublishApplicationEvent() { + orderService.placeOrder("customer1", "product1", "product2"); + + assertThat(testEventListener.getEvents()) + .hasSize(1).first() + .hasFieldOrPropertyWithValue("customerId", "customer1") + .hasFieldOrProperty("orderId") + .hasFieldOrProperty("timestamp"); + } + +} diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java new file mode 100644 index 0000000000..8973a99355 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/TestEventListener.java @@ -0,0 +1,29 @@ +package com.baeldung.springmodulith.application.events; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; + +@Component +class TestEventListener { + + private final List events = new ArrayList<>(); + + @EventListener + void onEvent(OrderCompletedEvent event) { + events.add(event); + } + + public List getEvents() { + return events; + } + + public void reset() { + events.clear(); + } +} + From 49e66a1a1b8f1d6617e6b518e40e95be89ae1193 Mon Sep 17 00:00:00 2001 From: emanueltrandafir1993 Date: Thu, 21 Mar 2024 23:40:12 +0100 Subject: [PATCH 25/92] BAEL-5747: added spring modulith test --- .../spring-boot-libraries-3/pom.xml | 6 ++++++ ...=> SpringModulithScenarioApiUnitTest.java} | 20 ++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) rename spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/{ApplicationEventsUnitTest.java => SpringModulithScenarioApiUnitTest.java} (52%) diff --git a/spring-boot-modules/spring-boot-libraries-3/pom.xml b/spring-boot-modules/spring-boot-libraries-3/pom.xml index 988ce0bafe..7766af84c8 100644 --- a/spring-boot-modules/spring-boot-libraries-3/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-3/pom.xml @@ -55,6 +55,12 @@ test + + org.springframework.modulith + spring-modulith-starter-test + 1.1.3 + + org.testcontainers kafka diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java similarity index 52% rename from spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java rename to spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java index 0ebf96b33f..17fe4a555c 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/ApplicationEventsUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java @@ -2,19 +2,18 @@ package com.baeldung.springmodulith.application.events; import com.baeldung.springmodulith.application.events.orders.OrderService; import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; -import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository.LoyalCustomer; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; - -import java.util.Optional; +import org.springframework.modulith.test.ApplicationModuleTest; +import org.springframework.modulith.test.Scenario; import static org.assertj.core.api.Assertions.assertThat; -@SpringBootTest +@ApplicationModuleTest @ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") -public class ApplicationEventsUnitTest { +public class SpringModulithScenarioApiUnitTest { @Autowired OrderService orderService; @@ -23,15 +22,8 @@ public class ApplicationEventsUnitTest { LoyalCustomersRepository loyalCustomers; @Test - void whenNewCustomerCompletesAnOrder_thenHeReceivesSingUpPointsPlusOrderPoints() { - orderService.placeOrder("customer1", "product1", "product2"); + void test(Scenario scenario) { - Optional customer = loyalCustomers.find("customer1"); - - assertThat(customer).isPresent() - .get() - .extracting(LoyalCustomer::points) - .isEqualTo(50 + 10); } } From 34fd8269e3848908615afbc7aa1712d7417a1f9a Mon Sep 17 00:00:00 2001 From: "emanuel.trandafir" Date: Fri, 22 Mar 2024 15:22:00 +0100 Subject: [PATCH 26/92] BAEL-7547: finishing spring modulith test --- .../events/rewards/LoyaltyPointsService.java | 9 ++---- .../events/EventListenerUnitTest.java | 8 ++--- .../events/EventPublisherUnitTest.java | 15 +++++---- .../SpringModulithScenarioApiUnitTest.java | 31 +++++++++++++++---- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java index 20af0caa6f..3febcf0d66 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java @@ -7,8 +7,7 @@ import org.springframework.stereotype.Service; @Service public class LoyaltyPointsService { - public static final int ORDER_COMPLETED_POINTS = 10; - public static final int SING_UP_POINTS = 50; + public static final int ORDER_COMPLETED_POINTS = 60; private final LoyalCustomersRepository loyalCustomers; public LoyaltyPointsService(LoyalCustomersRepository loyalCustomers) { @@ -17,11 +16,7 @@ public class LoyaltyPointsService { @EventListener public void onOrderCompleted(OrderCompletedEvent event) { - if (loyalCustomers.find(event.customerId()).isEmpty()) { - loyalCustomers.save(event.customerId()); - loyalCustomers.awardPoints(event.customerId(), SING_UP_POINTS); - } - + // business logic to award points to loyal customers loyalCustomers.awardPoints(event.customerId(), ORDER_COMPLETED_POINTS); } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java index b8ad79e6f1..104cc1690d 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java @@ -16,7 +16,7 @@ import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepo @SpringBootTest @ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") -public class EventListenerUnitTest { +class EventListenerUnitTest { @Autowired private LoyalCustomersRepository customers; @@ -31,9 +31,9 @@ public class EventListenerUnitTest { testEventPublisher.publishEvent(event); assertThat(customers.find("customer-1")) - .isPresent().get() - .hasFieldOrPropertyWithValue("customerId", "customer-1") - .hasFieldOrPropertyWithValue("points", 60); + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60); } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java index 0989bb5fd3..16f20defc3 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java @@ -1,18 +1,17 @@ package com.baeldung.springmodulith.application.events; -import static org.assertj.core.api.Assertions.assertThat; - +import com.baeldung.springmodulith.application.events.orders.OrderService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; -import com.baeldung.springmodulith.application.events.orders.OrderService; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") -public class EventPublisherUnitTest { +class EventPublisherUnitTest { @Autowired OrderService orderService; @@ -30,10 +29,10 @@ public class EventPublisherUnitTest { orderService.placeOrder("customer1", "product1", "product2"); assertThat(testEventListener.getEvents()) - .hasSize(1).first() - .hasFieldOrPropertyWithValue("customerId", "customer1") - .hasFieldOrProperty("orderId") - .hasFieldOrProperty("timestamp"); + .hasSize(1).first() + .hasFieldOrPropertyWithValue("customerId", "customer1") + .hasFieldOrProperty("orderId") + .hasFieldOrProperty("timestamp"); } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java index 17fe4a555c..8d262a24d0 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java @@ -1,19 +1,22 @@ package com.baeldung.springmodulith.application.events; +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; import com.baeldung.springmodulith.application.events.orders.OrderService; import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; - import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.ComponentScan; import org.springframework.modulith.test.ApplicationModuleTest; +import org.springframework.modulith.test.ApplicationModuleTest.BootstrapMode; import org.springframework.modulith.test.Scenario; +import java.time.Duration; +import java.time.Instant; + +import static java.time.Duration.ofMillis; import static org.assertj.core.api.Assertions.assertThat; @ApplicationModuleTest -@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") -public class SpringModulithScenarioApiUnitTest { +class SpringModulithScenarioApiUnitTest { @Autowired OrderService orderService; @@ -22,8 +25,24 @@ public class SpringModulithScenarioApiUnitTest { LoyalCustomersRepository loyalCustomers; @Test - void test(Scenario scenario) { - + void whenPlacingOrder_thenPublishOrderCompletedEvent(Scenario scenario) { + scenario.stimulate(() -> orderService.placeOrder("customer-1", "product-1", "product-2")) + .andWaitAtMost(ofMillis(500)) + .andWaitForEventOfType(OrderCompletedEvent.class) + .toArriveAndVerify(evt -> assertThat(evt) + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrProperty("orderId") + .hasFieldOrProperty("timestamp")); } + @Test + void whenReceivingPublishOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints(Scenario scenario) { + scenario.publish(new OrderCompletedEvent("order-1", "customer-1", Instant.now())) + .andWaitAtMost(ofMillis(500)) + .andWaitForStateChange(() -> loyalCustomers.find("customer-1")) + .andVerify(it -> assertThat(it) + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60)); + } } From 23ff3bc2fc1ffa701f17f9daa312cf6df7ab065a Mon Sep 17 00:00:00 2001 From: "emanuel.trandafir" Date: Fri, 22 Mar 2024 15:37:18 +0100 Subject: [PATCH 27/92] BAEL-7547: small fix --- .../events/rewards/LoyalCustomersRepository.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java index 764924232d..c4afae0d5d 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java @@ -13,18 +13,21 @@ public class LoyalCustomersRepository { public Optional find(String customerId) { return customers.stream() - .filter(it -> it.customerId().equals(customerId)) - .findFirst(); + .filter(it -> it.customerId().equals(customerId)) + .findFirst(); } public void awardPoints(String customerId, int points) { - var customer = find(customerId).orElseThrow(); + var customer = find(customerId) + .orElseGet(() -> save(new LoyalCustomer(customerId, 0))); + customers.remove(customer); customers.add(customer.addPoints(points)); } - public void save(String customerId) { - customers.add(new LoyalCustomer(customerId, 0)); + public LoyalCustomer save(LoyalCustomer customer) { + customers.add(customer); + return customer; } public boolean isLoyalCustomer(String customerId) { From fbd72d1a0967716ccf79d68ea05d0512b7d684bd Mon Sep 17 00:00:00 2001 From: emanueltrandafir1993 Date: Fri, 22 Mar 2024 22:11:09 +0100 Subject: [PATCH 28/92] BAEL-7547: removing timeouts --- .../application/events/SpringModulithScenarioApiUnitTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java index 8d262a24d0..f36a0c30e6 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/SpringModulithScenarioApiUnitTest.java @@ -27,7 +27,6 @@ class SpringModulithScenarioApiUnitTest { @Test void whenPlacingOrder_thenPublishOrderCompletedEvent(Scenario scenario) { scenario.stimulate(() -> orderService.placeOrder("customer-1", "product-1", "product-2")) - .andWaitAtMost(ofMillis(500)) .andWaitForEventOfType(OrderCompletedEvent.class) .toArriveAndVerify(evt -> assertThat(evt) .hasFieldOrPropertyWithValue("customerId", "customer-1") @@ -38,7 +37,6 @@ class SpringModulithScenarioApiUnitTest { @Test void whenReceivingPublishOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints(Scenario scenario) { scenario.publish(new OrderCompletedEvent("order-1", "customer-1", Instant.now())) - .andWaitAtMost(ofMillis(500)) .andWaitForStateChange(() -> loyalCustomers.find("customer-1")) .andVerify(it -> assertThat(it) .isPresent().get() From 9502473ac259620ddbb7869aa85ec306645e8999 Mon Sep 17 00:00:00 2001 From: emanueltrandafir1993 Date: Fri, 22 Mar 2024 22:30:39 +0100 Subject: [PATCH 29/92] BAEL-7547: adding h2 for non-testcontainers tests --- spring-boot-modules/spring-boot-libraries-3/pom.xml | 7 +++++++ .../application/events/EventListenerUnitTest.java | 1 - .../application/events/EventPublisherUnitTest.java | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-boot-libraries-3/pom.xml b/spring-boot-modules/spring-boot-libraries-3/pom.xml index 7766af84c8..39d594cdfe 100644 --- a/spring-boot-modules/spring-boot-libraries-3/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-3/pom.xml @@ -61,6 +61,13 @@ 1.1.3 + + com.h2database + h2 + 2.2.224 + test + + org.testcontainers kafka diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java index 104cc1690d..a54d003eb2 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java @@ -15,7 +15,6 @@ import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; @SpringBootTest -@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") class EventListenerUnitTest { @Autowired diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java index 16f20defc3..f4bdeee90d 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventPublisherUnitTest.java @@ -10,7 +10,6 @@ import org.springframework.context.annotation.ComponentScan; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -@ComponentScan(basePackages = "com.baeldung.springmodulith.application.events") class EventPublisherUnitTest { @Autowired From 7d14d37fda9fa878be3a6855751d5d20fd78a460 Mon Sep 17 00:00:00 2001 From: "emanuel.trandafir" Date: Thu, 28 Mar 2024 10:49:04 +0100 Subject: [PATCH 30/92] BAEL-7547: formatting & code review --- .../spring-boot-libraries-3/pom.xml | 38 +++++++------- .../application/events/orders/Order.java | 6 +-- .../events/orders/OrderRepository.java | 28 +++++----- .../events/orders/OrderService.java | 30 +++++------ .../rewards/LoyalCustomersRepository.java | 52 +++++++++---------- .../events/rewards/LoyaltyPointsService.java | 23 ++++---- .../events/EventListenerUnitTest.java | 28 +++++----- 7 files changed, 102 insertions(+), 103 deletions(-) diff --git a/spring-boot-modules/spring-boot-libraries-3/pom.xml b/spring-boot-modules/spring-boot-libraries-3/pom.xml index 39d594cdfe..e88ae4c078 100644 --- a/spring-boot-modules/spring-boot-libraries-3/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-3/pom.xml @@ -17,7 +17,6 @@ org.springframework.boot spring-boot-starter-data-jpa - org.springframework.kafka spring-kafka @@ -28,20 +27,27 @@ postgresql ${postgresql.version} + org.springframework.modulith spring-modulith-events-api - ${spring-modulith-events-kafka.version} + ${spring-modulith.version} org.springframework.modulith spring-modulith-events-kafka - ${spring-modulith-events-kafka.version} + ${spring-modulith.version} org.springframework.modulith spring-modulith-starter-jpa - ${spring-modulith-events-kafka.version} + ${spring-modulith.version} + + + org.springframework.modulith + spring-modulith-starter-test + ${spring-modulith.version} + test @@ -54,20 +60,6 @@ spring-boot-testcontainers test - - - org.springframework.modulith - spring-modulith-starter-test - 1.1.3 - - - - com.h2database - h2 - 2.2.224 - test - - org.testcontainers kafka @@ -86,7 +78,6 @@ ${testcontainers.version} test - org.testcontainers postgresql @@ -100,16 +91,23 @@ ${awaitility.version} test + + com.h2database + h2 + ${h2.version} + test + 17 3.1.5 - 1.1.2 + 1.1.3 1.19.3 4.2.0 42.3.1 + 2.2.224 diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java index a0ba6815bc..c448bd44dd 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/Order.java @@ -5,8 +5,8 @@ import java.util.List; record Order(String id, String customerId, List productIds, Instant timestamp) { - public Order(String customerId, List productIds) { - this(null, customerId, productIds, Instant.now()); - } + public Order(String customerId, List productIds) { + this(null, customerId, productIds, Instant.now()); + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java index d02b00d2d0..7c159e3582 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderRepository.java @@ -1,25 +1,27 @@ package com.baeldung.springmodulith.application.events.orders; -import org.springframework.stereotype.Component; - import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.springframework.stereotype.Component; + @Component class OrderRepository { - private final List orders = new ArrayList<>(); + private final List orders = new ArrayList<>(); - public Order save(Order order) { - order = new Order(UUID.randomUUID().toString(), order.customerId(), order.productIds(), order.timestamp()); - orders.add(order); - return order; - } + public Order save(Order order) { + order = new Order(UUID.randomUUID() + .toString(), order.customerId(), order.productIds(), order.timestamp()); + orders.add(order); + return order; + } - public List ordersByCustomer(String customerId) { - return orders.stream() - .filter(it -> it.customerId().equals(customerId)) - .toList(); - } + public List ordersByCustomer(String customerId) { + return orders.stream() + .filter(it -> it.customerId() + .equals(customerId)) + .toList(); + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java index c3b52d478b..c60792813c 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/orders/OrderService.java @@ -1,29 +1,29 @@ package com.baeldung.springmodulith.application.events.orders; +import java.util.Arrays; + import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; -import java.util.Arrays; - @Service public class OrderService { - private final OrderRepository repository; - private final ApplicationEventPublisher eventPublisher; + private final OrderRepository repository; + private final ApplicationEventPublisher eventPublisher; - public OrderService(OrderRepository orders, ApplicationEventPublisher eventsPublisher) { - this.repository = orders; - this.eventPublisher = eventsPublisher; - } + public OrderService(OrderRepository orders, ApplicationEventPublisher eventsPublisher) { + this.repository = orders; + this.eventPublisher = eventsPublisher; + } - public void placeOrder(String customerId, String... productIds) { - Order order = new Order(customerId, Arrays.asList(productIds)); - // business logic to validate and place the order + public void placeOrder(String customerId, String... productIds) { + Order order = new Order(customerId, Arrays.asList(productIds)); + // business logic to validate and place the order - Order savedOrder = repository.save(order); + Order savedOrder = repository.save(order); - OrderCompletedEvent event = new OrderCompletedEvent(savedOrder.id(), savedOrder.customerId(), savedOrder.timestamp()); - eventPublisher.publishEvent(event); - } + OrderCompletedEvent event = new OrderCompletedEvent(savedOrder.id(), savedOrder.customerId(), savedOrder.timestamp()); + eventPublisher.publishEvent(event); + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java index c4afae0d5d..29ba6fa8e2 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyalCustomersRepository.java @@ -1,44 +1,44 @@ package com.baeldung.springmodulith.application.events.rewards; -import org.springframework.stereotype.Component; - import java.util.ArrayList; import java.util.List; import java.util.Optional; +import org.springframework.stereotype.Component; + @Component public class LoyalCustomersRepository { - private List customers = new ArrayList<>(); + private List customers = new ArrayList<>(); - public Optional find(String customerId) { - return customers.stream() - .filter(it -> it.customerId().equals(customerId)) - .findFirst(); - } + public Optional find(String customerId) { + return customers.stream() + .filter(it -> it.customerId() + .equals(customerId)) + .findFirst(); + } - public void awardPoints(String customerId, int points) { - var customer = find(customerId) - .orElseGet(() -> save(new LoyalCustomer(customerId, 0))); + public void awardPoints(String customerId, int points) { + var customer = find(customerId).orElseGet(() -> save(new LoyalCustomer(customerId, 0))); - customers.remove(customer); - customers.add(customer.addPoints(points)); - } + customers.remove(customer); + customers.add(customer.addPoints(points)); + } - public LoyalCustomer save(LoyalCustomer customer) { - customers.add(customer); - return customer; - } + public LoyalCustomer save(LoyalCustomer customer) { + customers.add(customer); + return customer; + } - public boolean isLoyalCustomer(String customerId) { - return find(customerId).isPresent(); - } + public boolean isLoyalCustomer(String customerId) { + return find(customerId).isPresent(); + } - public record LoyalCustomer(String customerId, int points) { + public record LoyalCustomer(String customerId, int points) { - LoyalCustomer addPoints(int points) { - return new LoyalCustomer(customerId, this.points() + points); - } - } + LoyalCustomer addPoints(int points) { + return new LoyalCustomer(customerId, this.points() + points); + } + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java index 3febcf0d66..8cd1afe329 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/main/java/com/baeldung/springmodulith/application/events/rewards/LoyaltyPointsService.java @@ -1,23 +1,24 @@ package com.baeldung.springmodulith.application.events.rewards; -import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; +import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; + @Service public class LoyaltyPointsService { - public static final int ORDER_COMPLETED_POINTS = 60; - private final LoyalCustomersRepository loyalCustomers; + public static final int ORDER_COMPLETED_POINTS = 60; + private final LoyalCustomersRepository loyalCustomers; - public LoyaltyPointsService(LoyalCustomersRepository loyalCustomers) { - this.loyalCustomers = loyalCustomers; - } + public LoyaltyPointsService(LoyalCustomersRepository loyalCustomers) { + this.loyalCustomers = loyalCustomers; + } - @EventListener - public void onOrderCompleted(OrderCompletedEvent event) { - // business logic to award points to loyal customers - loyalCustomers.awardPoints(event.customerId(), ORDER_COMPLETED_POINTS); - } + @EventListener + public void onOrderCompleted(OrderCompletedEvent event) { + // business logic to award points to loyal customers + loyalCustomers.awardPoints(event.customerId(), ORDER_COMPLETED_POINTS); + } } diff --git a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java index a54d003eb2..676bc1173b 100644 --- a/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-3/src/test/java/com/baeldung/springmodulith/application/events/EventListenerUnitTest.java @@ -4,12 +4,10 @@ import static org.assertj.core.api.Assertions.assertThat; import java.time.Instant; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.annotation.ComponentScan; import com.baeldung.springmodulith.application.events.orders.OrderCompletedEvent; import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepository; @@ -17,22 +15,22 @@ import com.baeldung.springmodulith.application.events.rewards.LoyalCustomersRepo @SpringBootTest class EventListenerUnitTest { - @Autowired - private LoyalCustomersRepository customers; + @Autowired + private LoyalCustomersRepository customers; - @Autowired - private ApplicationEventPublisher testEventPublisher; + @Autowired + private ApplicationEventPublisher testEventPublisher; - @Test - void whenPublishingOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints() { - OrderCompletedEvent event = new OrderCompletedEvent("order-1", "customer-1", Instant.now()); + @Test + void whenPublishingOrderCompletedEvent_thenRewardCustomerWithLoyaltyPoints() { + OrderCompletedEvent event = new OrderCompletedEvent("order-1", "customer-1", Instant.now()); - testEventPublisher.publishEvent(event); + testEventPublisher.publishEvent(event); - assertThat(customers.find("customer-1")) - .isPresent().get() - .hasFieldOrPropertyWithValue("customerId", "customer-1") - .hasFieldOrPropertyWithValue("points", 60); - } + assertThat(customers.find("customer-1")) + .isPresent().get() + .hasFieldOrPropertyWithValue("customerId", "customer-1") + .hasFieldOrPropertyWithValue("points", 60); + } } From 9c539cdd3d6421a78a09bde301d797bfe54e2166 Mon Sep 17 00:00:00 2001 From: Sam Gardner Date: Thu, 28 Mar 2024 14:41:51 +0000 Subject: [PATCH 31/92] BAEL-7513 Move merge interval code to next module --- .../java/com/baeldung/algorithms/mergeintervals/Interval.java | 0 .../algorithms/mergeintervals/MergeOverlappingIntervals.java | 0 .../algorithms/mergeintervals/MergeIntervalsUnitTest.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename algorithms-modules/{algorithms-miscellaneous-7 => algorithms-miscellaneous-8}/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java (100%) rename algorithms-modules/{algorithms-miscellaneous-7 => algorithms-miscellaneous-8}/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java (100%) rename algorithms-modules/{algorithms-miscellaneous-7 => algorithms-miscellaneous-8}/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java (100%) diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java similarity index 100% rename from algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java rename to algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/Interval.java diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java similarity index 100% rename from algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java rename to algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java similarity index 100% rename from algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java rename to algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java From 1f5e5f0752bf3cf419cdf26704524d344b65880c Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Thu, 28 Mar 2024 19:36:23 +0100 Subject: [PATCH 32/92] JAVA-32063: Migrate spring-session-mongodb to spring boot 3 (#16184) --- .../spring-session-mongodb/pom.xml | 12 ++++--- .../HttpSessionConfig.java | 22 ++++++++++++ .../SpringSessionMongoDBController.java | 2 +- .../src/main/resources/application.properties | 2 +- .../java/com/baeldung/SpringContextTest.java | 9 +++-- .../SpringSessionMongoDBIntegrationTest.java | 36 +++++++++---------- .../src/test/resources/application.properties | 2 +- 7 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/HttpSessionConfig.java diff --git a/spring-web-modules/spring-session/spring-session-mongodb/pom.xml b/spring-web-modules/spring-session/spring-session-mongodb/pom.xml index 878dfeb690..d7b997b1af 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/pom.xml +++ b/spring-web-modules/spring-session/spring-session-mongodb/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../../parent-boot-2 + ../../../parent-boot-3 @@ -36,8 +36,8 @@ de.flapdoodle.embed - de.flapdoodle.embed.mongo - test + de.flapdoodle.embed.mongo.spring3x + ${embedded-mongodb.version} @@ -50,4 +50,8 @@ + + 4.12.2 + + \ No newline at end of file diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/HttpSessionConfig.java b/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/HttpSessionConfig.java new file mode 100644 index 0000000000..7cce840879 --- /dev/null +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/HttpSessionConfig.java @@ -0,0 +1,22 @@ +package com.baeldung.springsessionmongodb; + +import java.time.Duration; + +import org.springframework.context.annotation.Bean; +import org.springframework.session.data.mongo.JdkMongoSessionConverter; +import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession; +import org.springframework.session.web.http.DefaultCookieSerializer; + +@EnableMongoHttpSession +public class HttpSessionConfig { + @Bean + public JdkMongoSessionConverter jdkMongoSessionConverter() { + return new JdkMongoSessionConverter(Duration.ofMinutes(30)); + } + @Bean + public DefaultCookieSerializer customCookieSerializer() { + DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); + cookieSerializer.setUseHttpOnlyCookie(false); + return cookieSerializer; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java b/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java index b5cb4520a0..76e627e237 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java @@ -4,7 +4,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpSession; @RestController public class SpringSessionMongoDBController { diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties b/spring-web-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties index 1b1a6cfbcb..5c88e4e949 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.session.store-type=mongodb +#spring.session.store-type=mongodb server.port=8080 spring.data.mongodb.host=localhost diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java index babcdb2ccf..21b0595224 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java @@ -1,16 +1,15 @@ package com.baeldung; -import com.baeldung.springsessionmongodb.SpringSessionMongoDBApplication; import org.junit.Test; -import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) -@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +import com.baeldung.springsessionmongodb.SpringSessionMongoDBApplication; + +@SpringBootTest(classes = SpringSessionMongoDBApplication.class) public class SpringContextTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { + // Ensuring the context is spring boot application is started. } } diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java b/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java index 7233d07536..f811fb7cd4 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java @@ -1,24 +1,21 @@ package com.baeldung.springsessionmongodb; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.session.data.mongo.MongoIndexedSessionRepository; -import org.springframework.test.context.junit4.SpringRunner; - import java.util.Base64; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.session.Session; +import org.springframework.session.data.mongo.MongoIndexedSessionRepository; -@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class SpringSessionMongoDBIntegrationTest { +class SpringSessionMongoDBIntegrationTest { @LocalServerPort private int port; @@ -26,17 +23,18 @@ public class SpringSessionMongoDBIntegrationTest { @Autowired private MongoIndexedSessionRepository repository; - private TestRestTemplate restTemplate = new TestRestTemplate(); + private final TestRestTemplate restTemplate = new TestRestTemplate(); @Test - public void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() { + void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() { HttpEntity response = restTemplate .exchange("http://localhost:" + port, HttpMethod.GET, null, String.class); HttpHeaders headers = response.getHeaders(); String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE); - Assert.assertEquals(response.getBody(), - repository.findById(getSessionId(set_cookie)).getAttribute("count").toString()); + Session sessionById = repository.findById(getSessionId(set_cookie)); + + Assertions.assertEquals(response.getBody(), sessionById.getAttribute("count").toString()); } private String getSessionId(String cookie) { diff --git a/spring-web-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties b/spring-web-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties index bae3bfeeab..e585973c88 100644 --- a/spring-web-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties +++ b/spring-web-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties @@ -1,4 +1,4 @@ #To use a randomly allocated free port during tests to avoid port conflict across tests spring.data.mongodb.port=0 +de.flapdoodle.mongodb.embedded.version=5.0.5 -spring.mongodb.embedded.version=4.4.9 From 95b7834f6a21b5a40c9f4538de1b4af8b0800477 Mon Sep 17 00:00:00 2001 From: balasr3 Date: Thu, 28 Mar 2024 23:27:17 +0000 Subject: [PATCH 33/92] Revert "BAEL-7593: added implementation and test for kafka delayed message consumption" This reverts commit 98fcb6edefa15e3ffda8c5649f324b76386334bf. --- spring-kafka-3/pom.xml | 12 -- .../delay/DelayedMessageListenerAdapter.java | 93 -------------- .../kafka/delay/KafkaConsumerConfig.java | 64 ---------- .../kafka/delay/KafkaDelayApplication.java | 13 -- .../baeldung/spring/kafka/delay/Order.java | 27 ---- .../spring/kafka/delay/OrderListener.java | 37 ------ .../spring/kafka/delay/OrderService.java | 31 ----- .../delay/KafkaDelayIntegrationTest.java | 116 ------------------ 8 files changed, 393 deletions(-) delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java delete mode 100644 spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java delete mode 100644 spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java diff --git a/spring-kafka-3/pom.xml b/spring-kafka-3/pom.xml index 2d6def9c2c..894eab2576 100644 --- a/spring-kafka-3/pom.xml +++ b/spring-kafka-3/pom.xml @@ -22,7 +22,6 @@ org.springframework.kafka spring-kafka - 2.9.13 com.fasterxml.jackson.core @@ -51,16 +50,6 @@ ${awaitility.version} test - - org.projectlombok - lombok - ${lombok.version} - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-datatype.version} - @@ -68,6 +57,5 @@ 3.0.12 1.19.3 4.2.0 - 2.13.5 diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java deleted file mode 100644 index 339f18677a..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/DelayedMessageListenerAdapter.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import java.time.Duration; -import java.time.temporal.ChronoUnit; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.kafka.clients.consumer.Consumer; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.common.TopicPartition; -import org.springframework.kafka.listener.AcknowledgingConsumerAwareMessageListener; -import org.springframework.kafka.listener.KafkaBackoffException; -import org.springframework.kafka.listener.KafkaConsumerBackoffManager; -import org.springframework.kafka.listener.MessageListener; -import org.springframework.kafka.listener.adapter.AbstractDelegatingMessageListenerAdapter; -import org.springframework.kafka.support.Acknowledgment; - -public class DelayedMessageListenerAdapter extends AbstractDelegatingMessageListenerAdapter> implements AcknowledgingConsumerAwareMessageListener { - - private static final Duration DEFAULT_DELAY_VALUE = Duration.of(0, ChronoUnit.SECONDS); - - private final String listenerId; - - private final KafkaConsumerBackoffManager kafkaConsumerBackoffManager; - - private final Map delaysPerTopic = new ConcurrentHashMap<>(); - - private Duration defaultDelay = DEFAULT_DELAY_VALUE; - - public DelayedMessageListenerAdapter(MessageListener delegate, KafkaConsumerBackoffManager kafkaConsumerBackoffManager, String listenerId) { - super(delegate); - Objects.requireNonNull(kafkaConsumerBackoffManager, "kafkaConsumerBackoffManager cannot be null"); - Objects.requireNonNull(listenerId, "listenerId cannot be null"); - this.kafkaConsumerBackoffManager = kafkaConsumerBackoffManager; - this.listenerId = listenerId; - } - - @Override - public void onMessage(ConsumerRecord consumerRecord, Acknowledgment acknowledgment, Consumer consumer) throws KafkaBackoffException { - this.kafkaConsumerBackoffManager.backOffIfNecessary(createContext(consumerRecord, consumerRecord.timestamp() + delaysPerTopic.getOrDefault(consumerRecord.topic(), this.defaultDelay) - .toMillis(), consumer)); - invokeDelegateOnMessage(consumerRecord, acknowledgment, consumer); - } - - public void setDelayForTopic(String topic, Duration delay) { - Objects.requireNonNull(topic, "Topic cannot be null"); - Objects.requireNonNull(delay, "Delay cannot be null"); - this.logger.debug(() -> String.format("Setting delay %s for listener id %s", delay, this.listenerId)); - this.delaysPerTopic.put(topic, delay); - } - - public void setDefaultDelay(Duration delay) { - Objects.requireNonNull(delay, "Delay cannot be null"); - this.logger.debug(() -> String.format("Setting delay %s for listener id %s", delay, this.listenerId)); - this.defaultDelay = delay; - } - - private void invokeDelegateOnMessage(ConsumerRecord consumerRecord, Acknowledgment acknowledgment, Consumer consumer) { - switch (this.delegateType) { - case ACKNOWLEDGING_CONSUMER_AWARE: - this.delegate.onMessage(consumerRecord, acknowledgment, consumer); - break; - case ACKNOWLEDGING: - this.delegate.onMessage(consumerRecord, acknowledgment); - break; - case CONSUMER_AWARE: - this.delegate.onMessage(consumerRecord, consumer); - break; - case SIMPLE: - this.delegate.onMessage(consumerRecord); - } - } - - private KafkaConsumerBackoffManager.Context createContext(ConsumerRecord data, long nextExecutionTimestamp, Consumer consumer) { - return this.kafkaConsumerBackoffManager.createContext(nextExecutionTimestamp, this.listenerId, new TopicPartition(data.topic(), data.partition()), consumer); - } - - @Override - public void onMessage(ConsumerRecord data) { - onMessage(data, null, null); - } - - @Override - public void onMessage(ConsumerRecord data, Acknowledgment acknowledgment) { - onMessage(data, acknowledgment, null); - } - - @Override - public void onMessage(ConsumerRecord data, Consumer consumer) { - onMessage(data, null, consumer); - } -} \ No newline at end of file diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java deleted file mode 100644 index f84b7d3f2a..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaConsumerConfig.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import java.time.Duration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; -import org.springframework.kafka.core.ConsumerFactory; -import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; -import org.springframework.kafka.listener.ContainerPartitionPausingBackOffManager; -import org.springframework.kafka.listener.ContainerPausingBackOffHandler; -import org.springframework.kafka.listener.ContainerProperties; -import org.springframework.kafka.listener.KafkaConsumerBackoffManager; -import org.springframework.kafka.listener.ListenerContainerPauseService; -import org.springframework.kafka.listener.ListenerContainerRegistry; -import org.springframework.kafka.listener.MessageListener; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -@Configuration -public class KafkaConsumerConfig { - - @Bean - public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(ConsumerFactory consumerFactory, ListenerContainerRegistry registry, TaskScheduler scheduler) { - ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); - factory.setConsumerFactory(consumerFactory); - KafkaConsumerBackoffManager backOffManager = createBackOffManager(registry, scheduler); - factory.getContainerProperties() - .setAckMode(ContainerProperties.AckMode.RECORD); - factory.setContainerCustomizer(container -> { - DelayedMessageListenerAdapter delayedAdapter = wrapWithDelayedMessageListenerAdapter(backOffManager, container); - delayedAdapter.setDelayForTopic("web.orders", Duration.ofSeconds(10)); - delayedAdapter.setDefaultDelay(Duration.ZERO); - container.setupMessageListener(delayedAdapter); - }); - return factory; - } - - @Bean - public ObjectMapper objectMapper() { - return new ObjectMapper().registerModule(new JavaTimeModule()) - .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false); - } - - @Bean - public TaskScheduler taskScheduler() { - return new ThreadPoolTaskScheduler(); - } - - @SuppressWarnings("unchecked") - private DelayedMessageListenerAdapter wrapWithDelayedMessageListenerAdapter(KafkaConsumerBackoffManager backOffManager, ConcurrentMessageListenerContainer container) { - return new DelayedMessageListenerAdapter<>((MessageListener) container.getContainerProperties() - .getMessageListener(), backOffManager, container.getListenerId()); - } - - private ContainerPartitionPausingBackOffManager createBackOffManager(ListenerContainerRegistry registry, TaskScheduler scheduler) { - return new ContainerPartitionPausingBackOffManager(registry, new ContainerPausingBackOffHandler(new ListenerContainerPauseService(registry, scheduler))); - } - -} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java deleted file mode 100644 index 6303c045bc..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/KafkaDelayApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.kafka.annotation.EnableKafka; - -@EnableKafka -@SpringBootApplication -public class KafkaDelayApplication { - public static void main(String[] args) { - SpringApplication.run(KafkaDelayApplication.class, args); - } -} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java deleted file mode 100644 index e781e76466..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/Order.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.UUID; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class Order { - - private UUID orderId; - - private LocalDateTime orderGeneratedDateTime; - - private LocalDateTime orderProcessedTime; - - private List address; - - private double price; -} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java deleted file mode 100644 index 3c5c4a69e5..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderListener.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.kafka.annotation.RetryableTopic; -import org.springframework.kafka.listener.KafkaBackoffException; -import org.springframework.kafka.retrytopic.DltStrategy; -import org.springframework.stereotype.Component; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import groovy.util.logging.Slf4j; - -@Slf4j -@Component -public class OrderListener { - - private final OrderService orderService; - - private final ObjectMapper objectMapper; - - public OrderListener(OrderService orderService, ObjectMapper objectMapper) { - this.orderService = orderService; - this.objectMapper = objectMapper; - } - - @RetryableTopic(attempts = "1", include = KafkaBackoffException.class, dltStrategy = DltStrategy.NO_DLT) - @KafkaListener(topics = { "web.orders", "web.internal.orders" }, groupId = "orders") - public void handleOrders(String order) throws JsonProcessingException { - Order orderDetails = objectMapper.readValue(order, Order.class); - OrderService.Status orderStatus = orderService.findStatusById(orderDetails.getOrderId()); - if (orderStatus.equals(OrderService.Status.ORDER_CONFIRMED)) { - orderService.processOrder(orderDetails); - } - } - -} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java deleted file mode 100644 index f91e67c1d1..0000000000 --- a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/delay/OrderService.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.springframework.stereotype.Service; - -@Service -public class OrderService { - - HashMap orders = new HashMap<>(); - - public Status findStatusById(UUID orderId) { - return Status.ORDER_CONFIRMED; - } - - public void processOrder(Order order) { - order.setOrderProcessedTime(LocalDateTime.now()); - orders.put(order.getOrderId(), order); - } - - public Map getOrders() { - return orders; - } - - enum Status { - CREATED, ORDER_CONFIRMED, ORDER_PROCESSED, DELETED - } -} diff --git a/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java b/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java deleted file mode 100644 index 8264e67bb2..0000000000 --- a/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/delay/KafkaDelayIntegrationTest.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.baeldung.spring.kafka.delay; - -import static org.awaitility.Awaitility.await; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.UUID; - -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.serialization.StringSerializer; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.KafkaContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.utility.DockerImageName; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -@Testcontainers -@SpringBootTest(classes = KafkaDelayApplication.class) -class KafkaDelayIntegrationTest { - - @Container - private static KafkaContainer KAFKA = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")); - private static KafkaProducer testKafkaProducer; - private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()) - .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - - @Autowired - OrderService orderService; - - @DynamicPropertySource - static void setProps(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", KAFKA::getBootstrapServers); - } - - @BeforeAll - static void beforeAll() { - Properties props = new Properties(); - props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA.getBootstrapServers()); - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); - props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); - testKafkaProducer = new KafkaProducer<>(props); - } - - @Test - void givenKafkaBrokerExists_whenCreteOrderIsReceived_thenMessageShouldBeDelayed() throws Exception { - // Given - var orderId = UUID.randomUUID(); - Order order = Order.builder() - .orderId(orderId) - .price(1.0) - .orderGeneratedDateTime(LocalDateTime.now()) - .address(List.of("41 Felix Avenue, Luton")) - .build(); - - String orderString = objectMapper.writeValueAsString(order); - ProducerRecord record = new ProducerRecord<>("web.orders", orderString); - // When - testKafkaProducer.send(record) - .get(); - await().atMost(Duration.ofSeconds(1800)) - .until(() -> { - // then - Map orders = orderService.getOrders(); - return orders != null && orders.get(orderId) != null && Duration.between(orders.get(orderId) - .getOrderGeneratedDateTime(), orders.get(orderId) - .getOrderProcessedTime()) - .getSeconds() >= 10; - }); - } - - @Test - void givenKafkaBrokerExists_whenCreteOrderIsReceivedForOtherTopics_thenMessageShouldNotBeDelayed() throws Exception { - // Given - var orderId = UUID.randomUUID(); - Order order = Order.builder() - .orderId(orderId) - .price(1.0) - .orderGeneratedDateTime(LocalDateTime.now()) - .address(List.of("41 Felix Avenue, Luton")) - .build(); - - String orderString = objectMapper.writeValueAsString(order); - ProducerRecord record = new ProducerRecord<>("web.internal.orders", orderString); - // When - testKafkaProducer.send(record) - .get(); - await().atMost(Duration.ofSeconds(1800)) - .until(() -> { - // Then - Map orders = orderService.getOrders(); - System.out.println("Time...." + Duration.between(orders.get(orderId) - .getOrderGeneratedDateTime(), orders.get(orderId) - .getOrderProcessedTime()) - .getSeconds()); - return orders != null && orders.get(orderId) != null && Duration.between(orders.get(orderId) - .getOrderGeneratedDateTime(), orders.get(orderId) - .getOrderProcessedTime()) - .getSeconds() <= 1; - }); - } - -} \ No newline at end of file From c8b7d97ea79039906f93e4d9e3e79e7fb3623a23 Mon Sep 17 00:00:00 2001 From: technoddy Date: Thu, 28 Mar 2024 23:14:08 -0400 Subject: [PATCH 34/92] pr feedback --- .../src/main/java/com/baeldung/loki/DemoService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java index e9071c0de9..89fdcc48e8 100644 --- a/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java +++ b/spring-boot-modules/spring-boot-logging-loki/src/main/java/com/baeldung/loki/DemoService.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Service; @Service public class DemoService { - private final Logger LOG = LoggerFactory.getLogger(DemoService.class); + private static final Logger LOG = LoggerFactory.getLogger(DemoService.class); public void log() { LOG.info("DemoService.log invoked"); From 18f4f8b53e3e995a1aafe194ac685ab1e6b71069 Mon Sep 17 00:00:00 2001 From: DiegoMarti2 <150871541+DiegoMarti2@users.noreply.github.com> Date: Fri, 29 Mar 2024 06:09:49 +0200 Subject: [PATCH 35/92] baeldung-articles BAEL-7642 (#16255) --- .../TemporalAccessorToLocalDateUnitTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java diff --git a/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java new file mode 100644 index 0000000000..a634fe2a47 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/TemporalAccessorToLocalDate/TemporalAccessorToLocalDateUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.TemporalAccessorToLocalDate; + +import org.junit.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; + +import static org.junit.Assert.assertEquals; + +public class TemporalAccessorToLocalDateUnitTest { + String dateString = "2022-03-28"; + TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_LOCAL_DATE.parse(dateString); + + @Test + public void givenTemporalAccessor_whenUsingLocalDateFrom_thenConvertToLocalDate() { + LocalDate convertedDate = LocalDate.from(temporalAccessor); + assertEquals(LocalDate.of(2022, 3, 28), convertedDate); + } + + @Test + public void givenTemporalAccessor_whenUsingTemporalQueries_thenConvertToLocalDate() { + int year = temporalAccessor.query(TemporalQueries.localDate()).getYear(); + int month = temporalAccessor.query(TemporalQueries.localDate()).getMonthValue(); + int day = temporalAccessor.query(TemporalQueries.localDate()).getDayOfMonth(); + + LocalDate convertedDate = LocalDate.of(year, month, day); + assertEquals(LocalDate.of(2022, 3, 28), convertedDate); + } +} \ No newline at end of file From 5b40d07950e2f848a4d566489268abbdb114979a Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 29 Mar 2024 09:57:27 +0200 Subject: [PATCH 36/92] Update README.md --- docker-modules/docker-containers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-modules/docker-containers/README.md b/docker-modules/docker-containers/README.md index aa5167cc16..a16de50d8d 100644 --- a/docker-modules/docker-containers/README.md +++ b/docker-modules/docker-containers/README.md @@ -1,3 +1,3 @@ ### Relevant Articles: -- [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/ops/docker-jvm-heap-size) +- [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/java-docker-jvm-heap-size) From 358f60bb59423df9c8ca53d854d5b0a2870edb14 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 29 Mar 2024 10:07:04 +0200 Subject: [PATCH 37/92] JAVA-31609 move docker modules out of tutorials repo --- docker-modules/docker-caching/README.md | 3 - .../multi-module-caching/Dockerfile | 21 ------- .../multi-module-caching/Dockerfile-Buildkit | 13 ---- .../multi-module-caching/core-module/pom.xml | 28 --------- .../com/baeldung/maven_caching/CoreClass.java | 14 ----- .../multi-module-caching/pom.xml | 31 ---------- .../runner-module/pom.xml | 57 ----------------- .../MavenCachingApplication.java | 11 ---- docker-modules/docker-caching/pom.xml | 21 ------- .../single-module-caching/Dockerfile | 15 ----- .../single-module-caching/Dockerfile-Buildkit | 13 ---- .../single-module-caching/pom.xml | 55 ----------------- .../maven_caching/MavenCachingMain.java | 11 ---- docker-modules/docker-compose-2/README.md | 2 - .../communication_same_machine/Dockerfile | 3 - .../Dockerfile.node | 7 --- .../dns/docker-compose.yml | 20 ------ .../host_docker_internal/docker-compose.yml | 29 --------- .../host_docker_internal/index.js | 10 --- .../host_docker_internal/package.json | 14 ----- .../static_ip_bridge/docker-compose.yml | 34 ----------- .../static_ip_macvlan/docker-compose.yml | 36 ----------- docker-modules/docker-compose-2/pom.xml | 17 ------ docker-modules/docker-compose/Dockerfile | 4 -- docker-modules/docker-compose/README.md | 10 --- .../assign-static-ip/docker-compose.yml | 27 -------- .../docker-compose/assign-static-ip/init.sql | 13 ---- .../docker-compose-depends-on.yml | 14 ----- .../docker-compose-links.yml | 14 ----- .../docker-compose-network.yml | 36 ----------- .../exclude-subfolders/Dockerfile | 7 --- .../exclude-subfolders/docker-compose.yml | 12 ---- .../exclude-subfolders/package.json | 17 ------ .../exclude-subfolders/server.js | 7 --- .../docker-compose/intro/docker-compose.yml | 61 ------------------- .../docker-compose/latest-image/Dockerfile | 3 - .../docker-compose-build-image.yaml | 8 --- .../docker-compose-with-image.yaml | 9 --- .../multiple-mounts/bind_mount_and_volume.yml | 15 ----- .../docker-compose/multiple-mounts/init.sql | 9 --- .../multiple-mounts/multiple_bind_mounts.yml | 15 ----- .../multiple-mounts/multiple_volumes.yaml | 15 ----- docker-modules/docker-compose/pom.xml | 51 ---------------- .../docker-compose-independents.yml | 8 --- .../docker-compose-with-dependency.yml | 10 --- .../docker/app/DockAppApplication.java | 13 ---- .../docker/app/endpoint/MyController.java | 13 ---- .../src/main/resources/application.properties | 1 - .../app/DockAppApplicationUnitTest.java | 13 ---- .../docker-compose-my-app-service.yaml | 13 ---- .../docker-compose-redis-service.yaml | 13 ---- .../docker-compose-my-app-service.yaml | 12 ---- .../docker-compose-redis-service.yaml | 12 ---- .../docker-environment-variables/Dockerfile | 10 --- .../docker-environment-variables/README.md | 3 - .../docker-environment-variables/greetings.sh | 3 - docker-modules/docker-images/.gitignore | 33 ---------- docker-modules/docker-images/README.md | 7 --- .../comments/Dockerfile-add-arguments-to-from | 2 - .../comments/Dockerfile-add-arguments-to-run | 2 - .../docker-images/comments/Dockerfile-base | 2 - .../comments/Dockerfile-multi-line-comments | 4 -- .../comments/Dockerfile-parser-directives | 4 -- .../comments/Dockerfile-single-line-comments | 4 -- .../projects/config/Dockerfile | 2 - .../projects/config/nginx.conf | 8 --- .../projects/sample-site/docker/Dockerfile | 3 - .../sample-site/docker/Dockerfile-from-base | 2 - .../sample-site/docker/Dockerfile-script | 3 - .../sample-site/docker/build-docker.sh | 6 -- .../projects/sample-site/html/index.html | 10 --- .../Dockerfile-copy-2folders-atthesametime | 3 - .../Dockerfile-copy-directory | 3 - .../Dockerfile-merge-directory | 5 -- docker-modules/docker-images/pom.xml | 41 ------------- .../docker-images/private-repo/Dockerfile | 4 -- .../com/baeldung/docker/MainApplication.java | 13 ---- .../controllers/HelloWorldController.java | 12 ---- .../src/main/resources/application.properties | 1 - .../update-path/Dockerfile-bashrc | 5 -- .../docker-images/update-path/Dockerfile-env | 4 -- .../docker-images/update-path/Dockerfile-run | 4 -- .../dockerfile-git-strategies/.gitmodules | 4 -- .../dockerfile-git-strategies/Dockerfile | 13 ---- .../dockerfile-git-strategies/README.md | 3 - docker-modules/kaniko/README.md | 3 - docker-modules/kaniko/dockerfile | 2 - docker-modules/kaniko/pod.yaml | 19 ------ docker-modules/kaniko/volume-claim.yaml | 11 ---- docker-modules/kaniko/volume.yaml | 14 ----- docker-modules/pom.xml | 5 -- 91 files changed, 1197 deletions(-) delete mode 100644 docker-modules/docker-caching/README.md delete mode 100644 docker-modules/docker-caching/multi-module-caching/Dockerfile delete mode 100644 docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit delete mode 100644 docker-modules/docker-caching/multi-module-caching/core-module/pom.xml delete mode 100644 docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java delete mode 100644 docker-modules/docker-caching/multi-module-caching/pom.xml delete mode 100644 docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml delete mode 100644 docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java delete mode 100644 docker-modules/docker-caching/pom.xml delete mode 100644 docker-modules/docker-caching/single-module-caching/Dockerfile delete mode 100644 docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit delete mode 100644 docker-modules/docker-caching/single-module-caching/pom.xml delete mode 100644 docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java delete mode 100644 docker-modules/docker-compose-2/README.md delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/Dockerfile delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml delete mode 100644 docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml delete mode 100644 docker-modules/docker-compose-2/pom.xml delete mode 100644 docker-modules/docker-compose/Dockerfile delete mode 100644 docker-modules/docker-compose/README.md delete mode 100644 docker-modules/docker-compose/assign-static-ip/docker-compose.yml delete mode 100644 docker-modules/docker-compose/assign-static-ip/init.sql delete mode 100644 docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml delete mode 100644 docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml delete mode 100644 docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml delete mode 100644 docker-modules/docker-compose/exclude-subfolders/Dockerfile delete mode 100644 docker-modules/docker-compose/exclude-subfolders/docker-compose.yml delete mode 100644 docker-modules/docker-compose/exclude-subfolders/package.json delete mode 100644 docker-modules/docker-compose/exclude-subfolders/server.js delete mode 100644 docker-modules/docker-compose/intro/docker-compose.yml delete mode 100644 docker-modules/docker-compose/latest-image/Dockerfile delete mode 100644 docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml delete mode 100644 docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml delete mode 100644 docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml delete mode 100644 docker-modules/docker-compose/multiple-mounts/init.sql delete mode 100644 docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml delete mode 100644 docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml delete mode 100644 docker-modules/docker-compose/pom.xml delete mode 100644 docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml delete mode 100644 docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml delete mode 100644 docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java delete mode 100644 docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java delete mode 100644 docker-modules/docker-compose/src/main/resources/application.properties delete mode 100644 docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java delete mode 100644 docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml delete mode 100644 docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml delete mode 100644 docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml delete mode 100644 docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml delete mode 100644 docker-modules/docker-environment-variables/Dockerfile delete mode 100644 docker-modules/docker-environment-variables/README.md delete mode 100644 docker-modules/docker-environment-variables/greetings.sh delete mode 100644 docker-modules/docker-images/.gitignore delete mode 100644 docker-modules/docker-images/README.md delete mode 100644 docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from delete mode 100644 docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run delete mode 100644 docker-modules/docker-images/comments/Dockerfile-base delete mode 100644 docker-modules/docker-images/comments/Dockerfile-multi-line-comments delete mode 100644 docker-modules/docker-images/comments/Dockerfile-parser-directives delete mode 100644 docker-modules/docker-images/comments/Dockerfile-single-line-comments delete mode 100644 docker-modules/docker-images/files-outside-context/projects/config/Dockerfile delete mode 100644 docker-modules/docker-images/files-outside-context/projects/config/nginx.conf delete mode 100644 docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile delete mode 100644 docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base delete mode 100644 docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script delete mode 100644 docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh delete mode 100644 docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html delete mode 100644 docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime delete mode 100644 docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory delete mode 100644 docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory delete mode 100644 docker-modules/docker-images/pom.xml delete mode 100644 docker-modules/docker-images/private-repo/Dockerfile delete mode 100644 docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java delete mode 100644 docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java delete mode 100644 docker-modules/docker-images/src/main/resources/application.properties delete mode 100644 docker-modules/docker-images/update-path/Dockerfile-bashrc delete mode 100644 docker-modules/docker-images/update-path/Dockerfile-env delete mode 100644 docker-modules/docker-images/update-path/Dockerfile-run delete mode 100644 docker-modules/dockerfile-git-strategies/.gitmodules delete mode 100644 docker-modules/dockerfile-git-strategies/Dockerfile delete mode 100644 docker-modules/dockerfile-git-strategies/README.md delete mode 100644 docker-modules/kaniko/README.md delete mode 100644 docker-modules/kaniko/dockerfile delete mode 100644 docker-modules/kaniko/pod.yaml delete mode 100644 docker-modules/kaniko/volume-claim.yaml delete mode 100644 docker-modules/kaniko/volume.yaml diff --git a/docker-modules/docker-caching/README.md b/docker-modules/docker-caching/README.md deleted file mode 100644 index d985210683..0000000000 --- a/docker-modules/docker-caching/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant Articles: - -- [Caching Maven Dependencies with Docker](https://www.baeldung.com/ops/docker-cache-maven-dependencies) diff --git a/docker-modules/docker-caching/multi-module-caching/Dockerfile b/docker-modules/docker-caching/multi-module-caching/Dockerfile deleted file mode 100644 index 96ebe2a76b..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME - -ADD pom.xml $HOME -ADD core/pom.xml $HOME/core/pom.xml -ADD runner/pom.xml $HOME/runner/pom.xml - -RUN mvn -pl core verify --fail-never -ADD core $HOME/core -RUN mvn -pl core install -RUN mvn -pl runner verify --fail-never -ADD runner $HOME/runner -RUN mvn -pl core,runner package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/runner/target/runner-0.0.1-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit b/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit deleted file mode 100644 index e89ce38e4b..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/Dockerfile-Buildkit +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME - -ADD . $HOME -RUN --mount=type=cache,target=/root/.m2 mvn -f $HOME/pom.xml clean package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/runner/target/runner-0.0.1-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml b/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml deleted file mode 100644 index 991162ddfa..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/core-module/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - core-module - - - multi-module-caching - com.baeldung - 0.0.1-SNAPSHOT - - - - - com.google.guava - guava - ${guava.version} - - - - - 8 - 8 - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java b/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java deleted file mode 100644 index d8c73a331a..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/core-module/src/main/java/com/baeldung/maven_caching/CoreClass.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.maven_caching; - -import com.google.common.io.Files; - -public class CoreClass { - - public String method() { - return "Hello from core module!!"; - } - - public String dependencyMethod() { - return Files.simplifyPath("/home/app/test"); - } -} diff --git a/docker-modules/docker-caching/multi-module-caching/pom.xml b/docker-modules/docker-caching/multi-module-caching/pom.xml deleted file mode 100644 index b9977f8f3a..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - 4.0.0 - com.baeldung - multi-module-caching - 0.0.1-SNAPSHOT - Multi-module Maven caching example - pom - - - runner-module - core-module - - - - - - com.google.guava - guava - ${guava.version} - - - - - - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml b/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml deleted file mode 100644 index e608706864..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/runner-module/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - runner-module - - - multi-module-caching - com.baeldung - 0.0.1-SNAPSHOT - - - - - com.baeldung - core-module - 0.0.1-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - jar-with-dependencies - - - - true - com.baeldung.maven_caching.MavenCachingApplication - - - - - - assemble-all - package - - single - - - - - - - - - 8 - 8 - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java b/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java deleted file mode 100644 index 3673dd86c1..0000000000 --- a/docker-modules/docker-caching/multi-module-caching/runner-module/src/main/java/com/baeldung/maven_caching/MavenCachingApplication.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.maven_caching; - -public class MavenCachingApplication { - - public static void main(String[] args) { - CoreClass cc = new CoreClass(); - System.out.println(cc.method()); - System.out.println(cc.dependencyMethod()); - } - -} diff --git a/docker-modules/docker-caching/pom.xml b/docker-modules/docker-caching/pom.xml deleted file mode 100644 index 25572dfe4f..0000000000 --- a/docker-modules/docker-caching/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - 4.0.0 - docker-caching - docker-caching - pom - - - docker-modules - com.baeldung - 1.0.0-SNAPSHOT - - - - single-module-caching - multi-module-caching - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/Dockerfile b/docker-modules/docker-caching/single-module-caching/Dockerfile deleted file mode 100644 index 02157c0dd6..0000000000 --- a/docker-modules/docker-caching/single-module-caching/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME -ADD pom.xml $HOME -RUN mvn verify --fail-never - -ADD . $HOME -RUN mvn package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/target/single-module-caching-1.0-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit b/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit deleted file mode 100644 index 29384ce208..0000000000 --- a/docker-modules/docker-caching/single-module-caching/Dockerfile-Buildkit +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:alpine as build -ENV HOME=/usr/app -RUN mkdir -p $HOME -WORKDIR $HOME -ADD . $HOME - -RUN --mount=type=cache,target=/root/.m2 mvn -f $HOME/pom.xml clean package - -FROM openjdk:8-jdk-alpine - -COPY --from=build /usr/app/target/single-module-caching-1.0-SNAPSHOT-jar-with-dependencies.jar /app/runner.jar - -ENTRYPOINT java -jar /app/runner.jar \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/pom.xml b/docker-modules/docker-caching/single-module-caching/pom.xml deleted file mode 100644 index 1e90c7130e..0000000000 --- a/docker-modules/docker-caching/single-module-caching/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - com.baeldung - single-module-caching - 1.0-SNAPSHOT - - - - com.google.guava - guava - ${guava.version} - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - jar-with-dependencies - - - - true - com.baeldung.maven_caching.MavenCachingMain - - - - - - assemble-all - package - - single - - - - - - - - - 8 - 8 - UTF-8 - 33.0.0-jre - - - \ No newline at end of file diff --git a/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java b/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java deleted file mode 100644 index 4fbd8e5311..0000000000 --- a/docker-modules/docker-caching/single-module-caching/src/main/java/com/baeldung/maven_caching/MavenCachingMain.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.maven_caching; - -import com.google.common.io.Files; - -public class MavenCachingMain { - - public static void main(String[] args) { - System.out.println("Hello from maven_caching app!!!"); - System.out.println(Files.simplifyPath("/home/app/test")); - } -} diff --git a/docker-modules/docker-compose-2/README.md b/docker-modules/docker-compose-2/README.md deleted file mode 100644 index 353b85f154..0000000000 --- a/docker-modules/docker-compose-2/README.md +++ /dev/null @@ -1,2 +0,0 @@ -## Relevant Articles: -- [Communicating With Docker Containers on the Same Machine](https://www.baeldung.com/ops/docker-communicating-with-containers-on-same-machine) diff --git a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile b/docker-modules/docker-compose-2/communication_same_machine/Dockerfile deleted file mode 100644 index a0c4ebe59a..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM alpine:latest -MAINTAINER baeldung.com -RUN apk update && apk add iputils && apk add bash && apk add curl \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node b/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node deleted file mode 100644 index 6d8f0eff81..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/Dockerfile.node +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:8.16.1-alpine -WORKDIR /app -COPY host_docker_internal/package.json /app -COPY host_docker_internal/index.js /app -RUN npm install -CMD node index.js -EXPOSE 8080 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml deleted file mode 100644 index 0a06993241..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/dns/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - image: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - tty: true - ports: - - 8081:8081 - - alpine-app-2: - container_name: alpine-app-2 - image: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - tty: true - ports: - - 8080:8080 diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml deleted file mode 100644 index 8e7174a9a1..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/docker-compose.yml +++ /dev/null @@ -1,29 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - extra_hosts: # for linux hosts since version 20.10 - - host.docker.internal:host-gateway - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - networks: - - first-network - - node-app: - container_name: node-app - build: - context: .. - dockerfile: Dockerfile.node - image: node-app - ports: - - 8080:8080 - networks: - - second-network - -networks: - first-network: - driver: bridge - second-network: - driver: bridge \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js deleted file mode 100644 index cefae028e5..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/index.js +++ /dev/null @@ -1,10 +0,0 @@ -var express = require('express') -var app = express() - -app.get('/', function (req, res) { - res.send('Hello World!') -}) - -app.listen(8080, function () { - console.log('app listening on port 8080!') -}) \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json b/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json deleted file mode 100644 index cde98b1cfd..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/host_docker_internal/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "host_docker_internal", - "version": "1.0.0", - "description": "node js app", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Baeldung", - "license": "ISC", - "dependencies": { - "express": "^4.18.2" - } -} diff --git a/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml deleted file mode 100644 index 0193bd72fb..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/static_ip_bridge/docker-compose.yml +++ /dev/null @@ -1,34 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - ports: - - 8080:8080 - networks: - network-example: - ipv4_address: 10.5.0.2 - - alpine-app-2: - container_name: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-2 - tty: true - ports: - - 8081:8081 - networks: - network-example: - ipv4_address: 10.5.0.3 - -networks: - network-example: - driver: bridge - ipam: - config: - - subnet: 10.5.0.0/16 - gateway: 10.5.0.1 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml b/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml deleted file mode 100644 index cef1a0b5cb..0000000000 --- a/docker-modules/docker-compose-2/communication_same_machine/static_ip_macvlan/docker-compose.yml +++ /dev/null @@ -1,36 +0,0 @@ -services: - alpine-app-1: - container_name: alpine-app-1 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-1 - tty: true - ports: - - 8080:8080 - networks: - network-example: - ipv4_address: 192.168.2.2 - - alpine-app-2: - container_name: alpine-app-2 - build: - context: .. - dockerfile: Dockerfile - image: alpine-app-2 - tty: true - ports: - - 8081:8081 - networks: - network-example: - ipv4_address: 192.168.2.3 - -networks: - network-example: - driver: macvlan - driver_opts: - parent: enp0s3 - ipam: - config: - - subnet: 192.168.2.0/24 - gateway: 192.168.2.1 \ No newline at end of file diff --git a/docker-modules/docker-compose-2/pom.xml b/docker-modules/docker-compose-2/pom.xml deleted file mode 100644 index f7f01dc482..0000000000 --- a/docker-modules/docker-compose-2/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - docker-compose-2 - Demo project for Spring Boot and Docker - Module docker-compose-2 - pom - - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 - - - \ No newline at end of file diff --git a/docker-modules/docker-compose/Dockerfile b/docker-modules/docker-compose/Dockerfile deleted file mode 100644 index 382e1d3442..0000000000 --- a/docker-modules/docker-compose/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM openjdk:17-alpine -MAINTAINER baeldung.com -COPY target/docker-compose-0.0.1-SNAPSHOT.jar app.jar -ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/docker-modules/docker-compose/README.md b/docker-modules/docker-compose/README.md deleted file mode 100644 index 4631630e6a..0000000000 --- a/docker-modules/docker-compose/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## Relevant Articles: - -- [Introduction to Docker Compose](https://www.baeldung.com/ops/docker-compose) -- [How to Get Docker-Compose to Always Use the Latest Image](https://www.baeldung.com/ops/docker-compose-latest-image) -- [Communication Between Multiple Docker Compose Projects](https://www.baeldung.com/ops/docker-compose-communication) -- [Difference Between links and depends_on in Docker Compose](https://www.baeldung.com/ops/docker-compose-links-depends-on) -- [Mounting Multiple Volumes on a Docker Container](https://www.baeldung.com/ops/docker-mounting-multiple-volumes) -- [Rebuild Docker Container in Docker Compose](https://www.baeldung.com/rebuild-docker-container-compose) -- [Assign Static IP to Docker Container and Docker-Compose](https://www.baeldung.com/ops/docker-assign-static-ip-container) -- [Exclude a Sub-Folder When Adding a Volume to Docker](https://www.baeldung.com/ops/docker-exclude-sub-folder-when-adding-volume) diff --git a/docker-modules/docker-compose/assign-static-ip/docker-compose.yml b/docker-modules/docker-compose/assign-static-ip/docker-compose.yml deleted file mode 100644 index 9f555d1ad4..0000000000 --- a/docker-modules/docker-compose/assign-static-ip/docker-compose.yml +++ /dev/null @@ -1,27 +0,0 @@ -services: - db: - container_name: mysql_db - image: mysql:latest - environment: - - MYSQL_ROOT_PASSWORD=password - - MYSQL_ROOT_HOST=10.5.0.1 - ports: - - '3306:3306' - volumes: - - db:/var/lib/mysql - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - networks: - network: - ipv4_address: 10.5.0.5 - -volumes: - db: - driver: local - -networks: - network: - driver: bridge - ipam: - config: - - subnet: 10.5.0.0/16 - gateway: 10.5.0.1 \ No newline at end of file diff --git a/docker-modules/docker-compose/assign-static-ip/init.sql b/docker-modules/docker-compose/assign-static-ip/init.sql deleted file mode 100644 index e150bda7c8..0000000000 --- a/docker-modules/docker-compose/assign-static-ip/init.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE DATABASE IF NOT EXISTS test; -CREATE USER 'db_user'@'10.5.0.1' IDENTIFIED BY 'password'; -GRANT ALL PRIVILEGES ON *.* TO 'db_user'@'10.5.0.1' WITH GRANT OPTION; -FLUSH PRIVILEGES; - -use test; - -CREATE TABLE IF NOT EXISTS TEST_TABLE (id int, name varchar(255)); - - -INSERT INTO TEST_TABLE VALUES (1, 'TEST_1'); -INSERT INTO TEST_TABLE VALUES (2, 'TEST_2'); -INSERT INTO TEST_TABLE VALUES (3, 'TEST_3'); \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml deleted file mode 100644 index 1f9b42384e..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-depends-on.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - db: - image: postgres:latest - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - web-app: - image: web-app:latest - ports: - - 8080:8080 - depends_on: - - db \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml deleted file mode 100644 index cf84970b3c..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-links.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - db: - image: postgres:latest - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - web-app: - image: web-app:latest - ports: - - 8080:8080 - links: - - db \ No newline at end of file diff --git a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml b/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml deleted file mode 100644 index 6b6796b43d..0000000000 --- a/docker-modules/docker-compose/depends-on_vs_links/docker-compose-network.yml +++ /dev/null @@ -1,36 +0,0 @@ -services: - db: - image: postgres:latest - restart: always - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - ports: - - 5432:5432 - volumes: - - db:/var/lib/postgresql/data - networks: - - mynet - - web-app: - image: web-app:latest - depends_on: - - db - networks: - - mynet - ports: - - 8080:8080 - environment: - DB_HOST: db - DB_PORT: 5432 - DB_USER: postgres - DB_PASSWORD: postgres - DB_NAME: postgres - -networks: - mynet: - driver: bridge - -volumes: - db: - driver: local diff --git a/docker-modules/docker-compose/exclude-subfolders/Dockerfile b/docker-modules/docker-compose/exclude-subfolders/Dockerfile deleted file mode 100644 index 9aa1c4ea44..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:12.18.1 -ENV NODE_ENV=production -WORKDIR /app -COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --production -COPY . . -CMD [ "node", "server.js" ] \ No newline at end of file diff --git a/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml b/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml deleted file mode 100644 index 51e536ae5c..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -services: - node-app: - build: . - ports: - - 8080:8080 - volumes: - - .:/app - - my-vol:/app/node_modules/ - -volumes: - my-vol: - driver: local \ No newline at end of file diff --git a/docker-modules/docker-compose/exclude-subfolders/package.json b/docker-modules/docker-compose/exclude-subfolders/package.json deleted file mode 100644 index 118fb33610..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "app", - "version": "1.0.0", - "description": "", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "ronin-mocks": "^0.1.11", - "ronin-server": "^0.1.3" - } -} diff --git a/docker-modules/docker-compose/exclude-subfolders/server.js b/docker-modules/docker-compose/exclude-subfolders/server.js deleted file mode 100644 index 2ad342e4d4..0000000000 --- a/docker-modules/docker-compose/exclude-subfolders/server.js +++ /dev/null @@ -1,7 +0,0 @@ -const ronin = require('ronin-server') -const mocks = require('ronin-mocks') - -const server = ronin.server() - -server.use('/', mocks.server(server.Router(), false, true)) -server.start() \ No newline at end of file diff --git a/docker-modules/docker-compose/intro/docker-compose.yml b/docker-modules/docker-compose/intro/docker-compose.yml deleted file mode 100644 index 72d07d6392..0000000000 --- a/docker-modules/docker-compose/intro/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: '3' - -services: - -## VOLUME CONTAINER-TO-CONTAINER AND HOST-TO-CONTAINER TEST ## - - volumes-example-service: - image: alpine:latest - container_name: volumes-example-service - volumes: - - /tmp:/my-volumes/host-volume - - /home:/my-volumes/readonly-host-volume:ro - - my-named-global-volume:/my-volumes/named-global-volume - tty: true # Needed to keep the container running - - another-volumes-example-service: - image: alpine:latest - container_name: another-volumes-example-service - volumes: - - my-named-global-volume:/another-path/the-same-named-global-volume - tty: true # Needed to keep the container running - -## NETWORK CONTAINER-TO-CONTAINER TEST ## - - network-example-service: - image: karthequian/helloworld:latest - container_name: network-example-service - networks: - - my-shared-network - - another-service-in-the-same-network: - image: alpine:latest - container_name: another-service-in-the-same-network - networks: - - my-shared-network - - tty: true # Needed to keep the container running - - another-service-in-its-own-network: - image: alpine:latest - container_name: another-service-in-its-own-network - networks: - - my-private-network - tty: true # Needed to keep the container running - -## NETWORK HOST-TO-CONTAINER TEST ## - - network-example-service-available-to-host-on-port-1337: - image: karthequian/helloworld:latest - container_name: network-example-service-available-to-host-on-port-1337 - networks: - - my-shared-network - ports: - - "1337:80" - -volumes: - my-named-global-volume: - -networks: - my-shared-network: {} - my-private-network: {} diff --git a/docker-modules/docker-compose/latest-image/Dockerfile b/docker-modules/docker-compose/latest-image/Dockerfile deleted file mode 100644 index 71fc1a29d9..0000000000 --- a/docker-modules/docker-compose/latest-image/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM openjdk:11 -COPY target/docker-sample-app-0.0.1.jar app.jar -ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml b/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml deleted file mode 100644 index 27c1d8ee44..0000000000 --- a/docker-modules/docker-compose/latest-image/docker-compose-build-image.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: '2.4' -services: - db: - image: postgres - my_app: - build: . - ports: - - "8080:8080" diff --git a/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml b/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml deleted file mode 100644 index 9a8822f762..0000000000 --- a/docker-modules/docker-compose/latest-image/docker-compose-with-image.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: '2.4' -services: - db: - image: postgres - my_app: - image: "eugen/test-app:latest" - ports: - - "8080:8080" - diff --git a/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml b/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml deleted file mode 100644 index 1a8ea2dc25..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/bind_mount_and_volume.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - mysql-db: - image: mysql:latest - environment: - - MYSQL_ROOT_PASSWORD=password - - MYSQL_ROOT_HOST=localhost - ports: - - '3306:3306' - volumes: - - first-volume-data:/var/lib/mysql - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - -volumes: - first-volume-data: - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/init.sql b/docker-modules/docker-compose/multiple-mounts/init.sql deleted file mode 100644 index 345a9914fb..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/init.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE DATABASE IF NOT EXISTS test; - -use test; - -CREATE TABLE IF NOT EXISTS test_table (id int, description varchar(255)); - -INSERT INTO test_table VALUES (1, 'TEST_1'); -INSERT INTO test_table VALUES (2, 'TEST_2'); -INSERT INTO test_table VALUES (3, 'TEST_3'); \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml b/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml deleted file mode 100644 index 98c0275583..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/multiple_bind_mounts.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - localstack: - privileged: true - image: localstack/localstack:latest - container_name: localstack - ports: - - '4563-4599:4563-4599' - - '8055:8080' - environment: - - SERVICES=s3 - - DEBUG=1 - - DATA_DIR=/tmp/localstack/data - volumes: - - './.localstack:/var/lib/localstack' - - '/var/run/docker.sock:/var/run/docker.sock' \ No newline at end of file diff --git a/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml b/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml deleted file mode 100644 index bd722ac5b5..0000000000 --- a/docker-modules/docker-compose/multiple-mounts/multiple_volumes.yaml +++ /dev/null @@ -1,15 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - volumes: - - first-volume-data:/container-path-1 - - second-volume-data:/container-path-2:ro - -volumes: - first-volume-data: - driver: local - second-volume-data: - driver: local \ No newline at end of file diff --git a/docker-modules/docker-compose/pom.xml b/docker-modules/docker-compose/pom.xml deleted file mode 100644 index 90e0226c98..0000000000 --- a/docker-modules/docker-compose/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - docker-compose - Demo project for Spring Boot and Docker - - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.docker.app.DockAppApplication - - - - - repackage - - - - - - - - \ No newline at end of file diff --git a/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml b/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml deleted file mode 100644 index edf0934bc9..0000000000 --- a/docker-modules/docker-compose/rebuild-container/docker-compose-independents.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: "3.9" -services: - ubuntu: - image: "ubuntu:latest" - tty: true - alpine: - image: "alpine:latest" - tty: true \ No newline at end of file diff --git a/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml b/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml deleted file mode 100644 index 49852dbd78..0000000000 --- a/docker-modules/docker-compose/rebuild-container/docker-compose-with-dependency.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: "3.9" -services: - ubuntu: - image: "ubuntu:latest" - tty: true - depends_on: - - "alpine" - alpine: - image: "alpine:latest" - tty: true \ No newline at end of file diff --git a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java b/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java deleted file mode 100644 index e7ff52015c..0000000000 --- a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/DockAppApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker.app; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DockAppApplication { - - public static void main(String[] args) { - SpringApplication.run(DockAppApplication.class, args); - } - -} diff --git a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java b/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java deleted file mode 100644 index d46c57e606..0000000000 --- a/docker-modules/docker-compose/src/main/java/com/baeldung/docker/app/endpoint/MyController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker.app.endpoint; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class MyController { - - @GetMapping - public String version() { - return "1.7"; - } -} diff --git a/docker-modules/docker-compose/src/main/resources/application.properties b/docker-modules/docker-compose/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/docker-modules/docker-compose/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java b/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java deleted file mode 100644 index 7220766988..0000000000 --- a/docker-modules/docker-compose/src/test/java/com/baeldung/docker/app/DockAppApplicationUnitTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker.app; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DockAppApplicationUnitTest { - - @Test - void contextLoads() { - } - -} diff --git a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml deleted file mode 100644 index 42e9eec8a1..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-my-app-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - networks: - - my-app - -networks: - my-app: - name: redis_network - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml deleted file mode 100644 index ef9573a803..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/create-network-from-service/docker-compose-redis-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -services: - redis: - image: redis:latest - container_name: redis - ports: - - '6379:6379' - networks: - - network - -networks: - network: - driver: bridge - name: redis_network diff --git a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml deleted file mode 100644 index f3310108ce..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-my-app-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - my_app: - image: web-app:latest - container_name: web-app - ports: - - "8080:8080" - networks: - - network-example - -networks: - network-example: - external: true \ No newline at end of file diff --git a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml b/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml deleted file mode 100644 index 2cf44a05d6..0000000000 --- a/docker-modules/docker-compose/two-compose-share-same-network/join-existing-network/docker-compose-redis-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - redis: - image: redis:latest - container_name: redis - ports: - - '6379:6379' - networks: - - network-example - -networks: - network-example: - external: true diff --git a/docker-modules/docker-environment-variables/Dockerfile b/docker-modules/docker-environment-variables/Dockerfile deleted file mode 100644 index dcf69ec2cd..0000000000 --- a/docker-modules/docker-environment-variables/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM alpine:latest - -ARG name -ENV env_name $name - -COPY greetings.sh . - -RUN chmod +x /greetings.sh - -CMD ["/greetings.sh"] \ No newline at end of file diff --git a/docker-modules/docker-environment-variables/README.md b/docker-modules/docker-environment-variables/README.md deleted file mode 100644 index 12da2931a3..0000000000 --- a/docker-modules/docker-environment-variables/README.md +++ /dev/null @@ -1,3 +0,0 @@ - -## Relevant Articles: -- [How to Pass Environment Variable Value into Dockerfile](https://www.baeldung.com/ops/dockerfile-env-variable) diff --git a/docker-modules/docker-environment-variables/greetings.sh b/docker-modules/docker-environment-variables/greetings.sh deleted file mode 100644 index 6b9cd61105..0000000000 --- a/docker-modules/docker-environment-variables/greetings.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo Hello $env_name \ No newline at end of file diff --git a/docker-modules/docker-images/.gitignore b/docker-modules/docker-images/.gitignore deleted file mode 100644 index 549e00a2a9..0000000000 --- a/docker-modules/docker-images/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/docker-modules/docker-images/README.md b/docker-modules/docker-images/README.md deleted file mode 100644 index 9ad9f6a3df..0000000000 --- a/docker-modules/docker-images/README.md +++ /dev/null @@ -1,7 +0,0 @@ -### Relevant Articles: - -- [Pushing a Docker Image to a Private Repository](https://www.baeldung.com/ops/docker-push-image-to-private-repository) -- [How to Include Files Outside of Docker’s Build Context](https://www.baeldung.com/ops/docker-include-files-outside-build-context) -- [Adding a Comment in a Dockerfile](https://www.baeldung.com/ops/docker-dockerfile-comments) -- [Updating PATH Environment Variable in Dockerfile](https://www.baeldung.com/ops/dockerfile-path-environment-variable) -- [Keep Subdirectory Structure in Dockerfile Copy](https://www.baeldung.com/ops/dockerfile-copy-same-subdirectory-structure) diff --git a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from b/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from deleted file mode 100644 index 2de102e20d..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-from +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest # Declare parent image -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run b/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run deleted file mode 100644 index 186db7683c..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-add-arguments-to-run +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' # Print sentence \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-base b/docker-modules/docker-images/comments/Dockerfile-base deleted file mode 100644 index a25c52b8da..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-base +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-multi-line-comments b/docker-modules/docker-images/comments/Dockerfile-multi-line-comments deleted file mode 100644 index 7c1fc43d34..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-multi-line-comments +++ /dev/null @@ -1,4 +0,0 @@ -# This file is a demonstration -# For a Baeldung article -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial' \ No newline at end of file diff --git a/docker-modules/docker-images/comments/Dockerfile-parser-directives b/docker-modules/docker-images/comments/Dockerfile-parser-directives deleted file mode 100644 index e8341b6cec..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-parser-directives +++ /dev/null @@ -1,4 +0,0 @@ -# escape=` -FROM ubuntu:latest -RUN echo 'This is a Baeldung tutorial&' ` - && echo 'Print more stuff' diff --git a/docker-modules/docker-images/comments/Dockerfile-single-line-comments b/docker-modules/docker-images/comments/Dockerfile-single-line-comments deleted file mode 100644 index a7581769aa..0000000000 --- a/docker-modules/docker-images/comments/Dockerfile-single-line-comments +++ /dev/null @@ -1,4 +0,0 @@ -# Declare parent image -FROM ubuntu:latest -# Print sentence -RUN echo 'This is a Baeldung tutorial' diff --git a/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile b/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile deleted file mode 100644 index 754f9f9be3..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/config/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM nginx:latest -COPY nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf b/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf deleted file mode 100644 index 944da2f112..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/config/nginx.conf +++ /dev/null @@ -1,8 +0,0 @@ -events {} - -http { - server { - listen 80; - index index.html; - } -} diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile deleted file mode 100644 index bda0bbe257..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest -COPY sample-site/html/* /etc/nginx/html/ -COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base deleted file mode 100644 index 1b72414bc0..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-from-base +++ /dev/null @@ -1,2 +0,0 @@ -FROM sample-site-base:latest -COPY html/* /etc/nginx/html/ diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script deleted file mode 100644 index 572028f19f..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/Dockerfile-script +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest -COPY html/* /etc/nginx/html/ -COPY config/nginx.conf /etc/nginx/nginx.conf diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh b/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh deleted file mode 100644 index e84687b7b7..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/docker/build-docker.sh +++ /dev/null @@ -1,6 +0,0 @@ -mkdir tmp-context -cp -R ../html tmp-context/ -cp -R ../../config tmp-context/ -cp Dockerfile-script tmp-context/Dockerfile -docker build -t sample-site:latest tmp-context -rm -rf tmp-context diff --git a/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html b/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html deleted file mode 100644 index 85f287fad7..0000000000 --- a/docker-modules/docker-images/files-outside-context/projects/sample-site/html/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Sample Site - - -

Welcome to the first page of the site

- - diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime deleted file mode 100644 index 3d6436aaa5..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-2folders-atthesametime +++ /dev/null @@ -1,3 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ folder2/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory deleted file mode 100644 index 364c82eb5d..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-copy-directory +++ /dev/null @@ -1,3 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory b/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory deleted file mode 100644 index 16427d90fc..0000000000 --- a/docker-modules/docker-images/keep-subdirectory-structure-in-Dockerfile-copy/Dockerfile-merge-directory +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:latest -COPY folder1/ /workdir/ -RUN ls --recursive /workdir/ -COPY folder2/ /workdir/ -RUN ls --recursive /workdir/ \ No newline at end of file diff --git a/docker-modules/docker-images/pom.xml b/docker-modules/docker-images/pom.xml deleted file mode 100644 index 4d0b20eea0..0000000000 --- a/docker-modules/docker-images/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - docker-images - Example application to showcase Docker images features - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/docker-modules/docker-images/private-repo/Dockerfile b/docker-modules/docker-images/private-repo/Dockerfile deleted file mode 100644 index 42a13e2a93..0000000000 --- a/docker-modules/docker-images/private-repo/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM openjdk:11 -ARG JAR_FILE=target/*.jar -COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java b/docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java deleted file mode 100644 index b5e46f3eac..0000000000 --- a/docker-modules/docker-images/src/main/java/com/baeldung/docker/MainApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.docker; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class MainApplication { - - public static void main(String[] args) { - SpringApplication.run(MainApplication .class, args); - } - -} diff --git a/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java b/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java deleted file mode 100644 index f7ade95075..0000000000 --- a/docker-modules/docker-images/src/main/java/com/baeldung/docker/controllers/HelloWorldController.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.docker.controllers; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class HelloWorldController { - @GetMapping("/helloworld") - String helloWorld() { - return "Hello World!"; - } -} \ No newline at end of file diff --git a/docker-modules/docker-images/src/main/resources/application.properties b/docker-modules/docker-images/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/docker-modules/docker-images/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docker-modules/docker-images/update-path/Dockerfile-bashrc b/docker-modules/docker-images/update-path/Dockerfile-bashrc deleted file mode 100644 index 4ac110e16b..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-bashrc +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -RUN echo "export PATH=$PATH:/etc/profile" >> ~/.bashrc -RUN cat ~/.bashrc -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/docker-images/update-path/Dockerfile-env b/docker-modules/docker-images/update-path/Dockerfile-env deleted file mode 100644 index 744fba15ed..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-env +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -ENV PATH="$PATH:/etc/profile" -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/docker-images/update-path/Dockerfile-run b/docker-modules/docker-images/update-path/Dockerfile-run deleted file mode 100644 index 1e97f66965..0000000000 --- a/docker-modules/docker-images/update-path/Dockerfile-run +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:latest -RUN echo $PATH -RUN export PATH="$PATH:/etc/profile"; echo $PATH -RUN echo $PATH \ No newline at end of file diff --git a/docker-modules/dockerfile-git-strategies/.gitmodules b/docker-modules/dockerfile-git-strategies/.gitmodules deleted file mode 100644 index aa3911dfc3..0000000000 --- a/docker-modules/dockerfile-git-strategies/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "project"] - path = project - url = https://github.com/eugenp/tutorials.git - branch = master \ No newline at end of file diff --git a/docker-modules/dockerfile-git-strategies/Dockerfile b/docker-modules/dockerfile-git-strategies/Dockerfile deleted file mode 100644 index 98911bdcbd..0000000000 --- a/docker-modules/dockerfile-git-strategies/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -ADD git-strategies /project/ -ADD /build/ /project/ -ADD /output/project.jar /project/ - -ADD ssh-private-key /root/.ssh/id_rsa -RUN git clone git@github.com:eugenp/tutorials.git - -ARG username=$GIT_USERNAME -ARG password=$GIT_PASSWORD -RUN git clone https://username:password@github.com:eugenp/tutorials.git - -VOLUME /build/ /project/ - diff --git a/docker-modules/dockerfile-git-strategies/README.md b/docker-modules/dockerfile-git-strategies/README.md deleted file mode 100644 index 7e27328678..0000000000 --- a/docker-modules/dockerfile-git-strategies/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant Articles: - -- [Dockerfile Strategies for Git](https://www.baeldung.com/ops/dockerfile-git-strategies) diff --git a/docker-modules/kaniko/README.md b/docker-modules/kaniko/README.md deleted file mode 100644 index a69a3cb683..0000000000 --- a/docker-modules/kaniko/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [An Introduction to Kaniko](https://www.baeldung.com/ops/kaniko) diff --git a/docker-modules/kaniko/dockerfile b/docker-modules/kaniko/dockerfile deleted file mode 100644 index 0290bf16ed..0000000000 --- a/docker-modules/kaniko/dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM ubuntu -ENTRYPOINT ["/bin/bash", "-c", "echo hello"] diff --git a/docker-modules/kaniko/pod.yaml b/docker-modules/kaniko/pod.yaml deleted file mode 100644 index 17f9a81b6d..0000000000 --- a/docker-modules/kaniko/pod.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: kaniko -spec: - containers: - - name: kaniko - image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=/workspace/dockerfile", - "--context=dir://workspace", - "--no-push"] - volumeMounts: - - name: dockerfile-storage - mountPath: /workspace - restartPolicy: Never - volumes: - - name: dockerfile-storage - persistentVolumeClaim: - claimName: dockerfile-claim diff --git a/docker-modules/kaniko/volume-claim.yaml b/docker-modules/kaniko/volume-claim.yaml deleted file mode 100644 index 7a1abbf05c..0000000000 --- a/docker-modules/kaniko/volume-claim.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: dockerfile-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: local-storage diff --git a/docker-modules/kaniko/volume.yaml b/docker-modules/kaniko/volume.yaml deleted file mode 100644 index e44663ec5a..0000000000 --- a/docker-modules/kaniko/volume.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: dockerfile - labels: - type: local -spec: - capacity: - storage: 10Gi - accessModes: - - ReadWriteOnce - storageClassName: local-storage - hostPath: - path: /home/docker/kaniko # Path to the local mount directory that was setup diff --git a/docker-modules/pom.xml b/docker-modules/pom.xml index bf35ef23ab..422b65023c 100644 --- a/docker-modules/pom.xml +++ b/docker-modules/pom.xml @@ -14,16 +14,11 @@ - docker-caching - docker-compose - docker-compose-2 docker-containers - docker-images docker-spring-boot docker-spring-boot-postgres docker-java-jar jib - \ No newline at end of file From 2df107ef2b19790287d2d705fa217f2edd187a76 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 29 Mar 2024 17:22:25 +0700 Subject: [PATCH 38/92] [BAEL-7557] SkipList-implementation-in-Java (#16253) --- .../baeldung/algorithms/skiplist/Node.java | 11 +++ .../algorithms/skiplist/SkipList.java | 92 +++++++++++++++++++ .../algorithms/skiplist/SkipListUnitTest.java | 34 +++++++ 3 files changed, 137 insertions(+) create mode 100644 algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java create mode 100644 algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java create mode 100644 algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java new file mode 100644 index 0000000000..52192415df --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/Node.java @@ -0,0 +1,11 @@ +package com.baeldung.algorithms.skiplist; + +class Node { + int value; + Node[] forward; // array to hold references to different levels + + public Node(int value, int level) { + this.value = value; + this.forward = new Node[level + 1]; // level + 1 because level is 0-based + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java new file mode 100644 index 0000000000..53f7a3b0c8 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/skiplist/SkipList.java @@ -0,0 +1,92 @@ +package com.baeldung.algorithms.skiplist; + + +import java.util.Random; + +public class SkipList { + private Node head; + private int maxLevel; + private int level; + private Random random; + + public SkipList() { + maxLevel = 16; // maximum number of levels + level = 0; // current level of SkipList + head = new Node(Integer.MIN_VALUE, maxLevel); + random = new Random(); + } + + public void insert(int value) { + Node[] update = new Node[maxLevel + 1]; + Node current = this.head; + + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + update[i] = current; + } + + current = current.forward[0]; + + if (current == null || current.value != value) { + int lvl = randomLevel(); + + if (lvl > level) { + for (int i = level + 1; i <= lvl; i++) { + update[i] = head; + } + level = lvl; + } + + Node newNode = new Node(value, lvl); + for (int i = 0; i <= lvl; i++) { + newNode.forward[i] = update[i].forward[i]; + update[i].forward[i] = newNode; + } + } + } + + public boolean search(int value) { + Node current = this.head; + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + } + current = current.forward[0]; + return current != null && current.value == value; + } + + public void delete(int value) { + Node[] update = new Node[maxLevel + 1]; + Node current = this.head; + + for (int i = level; i >= 0; i--) { + while (current.forward[i] != null && current.forward[i].value < value) { + current = current.forward[i]; + } + update[i] = current; + } + current = current.forward[0]; + + if (current != null && current.value == value) { + for (int i = 0; i <= level; i++) { + if (update[i].forward[i] != current) break; + update[i].forward[i] = current.forward[i]; + } + + while (level > 0 && head.forward[level] == null) { + level--; + } + } + } + + private int randomLevel() { + int lvl = 0; + while (lvl < maxLevel && random.nextDouble() < 0.5) { + lvl++; + } + return lvl; + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java new file mode 100644 index 0000000000..6f8e5d042c --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/skiplist/SkipListUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.algorithms.skiplist; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SkipListUnitTest { + + @Test + public void givenSkipList_WhenInsert_ThenSearchFound() { + SkipList skipList = new SkipList(); + + skipList.insert(3); + assertTrue(skipList.search(3), "Should find 3"); + + assertFalse(skipList.search(99), "Should not find 99"); + } + + @Test + public void givenSkipList_WhenDeleteElement_ThenRemoveFromList() { + SkipList skipList = new SkipList(); + + skipList.insert(3); + skipList.insert(7); + + skipList.delete(3); + assertFalse(skipList.search(3), "3 should have been deleted"); + + skipList.delete(99); + assertTrue(skipList.search(7), "7 should still exist"); + } + +} From a6ea78aa471631e2b89f28d2e0b5a4e6b61da154 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 29 Mar 2024 17:26:43 +0700 Subject: [PATCH 39/92] [JAVA-29082] Split-or-move-spring-data-jpa-repo-module (#16252) * [JAVA-29082] Split-or-move-spring-data-jpa-repo-module * [JAVA-29082] Split-or-move-spring-data-jpa-repo-module --- persistence-modules/spring-data-jpa-repo-2/README.md | 2 ++ .../storedprocedure/StoredProcedureApplication.java | 2 +- .../storedprocedure/controller/CarController.java | 9 ++++----- .../data/persistence}/storedprocedure/entity/Car.java | 2 +- .../storedprocedure/repository/CarRepository.java | 7 +++---- .../persistence}/storedprocedure/service/CarService.java | 9 ++++----- .../src/main/resources/car-mysql.sql | 0 persistence-modules/spring-data-jpa-repo/README.md | 1 - 8 files changed, 15 insertions(+), 17 deletions(-) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence}/storedprocedure/StoredProcedureApplication.java (83%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence}/storedprocedure/controller/CarController.java (86%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence}/storedprocedure/entity/Car.java (93%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence}/storedprocedure/repository/CarRepository.java (87%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence}/storedprocedure/service/CarService.java (81%) rename persistence-modules/{spring-data-jpa-repo => spring-data-jpa-repo-2}/src/main/resources/car-mysql.sql (100%) diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md index 8c588405f7..d377104c02 100644 --- a/persistence-modules/spring-data-jpa-repo-2/README.md +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -7,4 +7,6 @@ - [Difference Between JPA and Spring Data JPA](https://www.baeldung.com/spring-data-jpa-vs-jpa) - [Differences Between Spring Data JPA findFirst() and findTop()](https://www.baeldung.com/spring-data-jpa-findfirst-vs-findtop) - [Difference Between findBy and findAllBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-find-by-vs-find-all-by) +- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) + - More articles: [[<-- prev]](../spring-data-jpa-repo) diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java similarity index 83% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java index 5f05764e21..0100beec55 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/StoredProcedureApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.storedprocedure; +package com.baeldung.spring.data.persistence.storedprocedure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java similarity index 86% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java index 6aef600d01..6a12e4e93b 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/controller/CarController.java @@ -1,14 +1,13 @@ -package com.baeldung.storedprocedure.controller; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.controller; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; +import com.baeldung.spring.data.persistence.storedprocedure.service.CarService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.storedprocedure.entity.Car; -import com.baeldung.storedprocedure.service.CarService; +import java.util.List; @RestController public class CarController { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java similarity index 93% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java index 0a61a16e24..53f1d8557e 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/entity/Car.java @@ -1,4 +1,4 @@ -package com.baeldung.storedprocedure.entity; +package com.baeldung.spring.data.persistence.storedprocedure.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java similarity index 87% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java index 3d9428628e..9366a86445 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/repository/CarRepository.java @@ -1,14 +1,13 @@ -package com.baeldung.storedprocedure.repository; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.repository; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; 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 org.springframework.stereotype.Repository; -import com.baeldung.storedprocedure.entity.Car; +import java.util.List; @Repository public interface CarRepository extends JpaRepository { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java similarity index 81% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java rename to persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java index 104f46e324..ff2a20601e 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/storedprocedure/service/CarService.java @@ -1,12 +1,11 @@ -package com.baeldung.storedprocedure.service; - -import java.util.List; +package com.baeldung.spring.data.persistence.storedprocedure.service; +import com.baeldung.spring.data.persistence.storedprocedure.entity.Car; +import com.baeldung.spring.data.persistence.storedprocedure.repository.CarRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.baeldung.storedprocedure.entity.Car; -import com.baeldung.storedprocedure.repository.CarRepository; +import java.util.List; @Service public class CarService { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/car-mysql.sql similarity index 100% rename from persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql rename to persistence-modules/spring-data-jpa-repo-2/src/main/resources/car-mysql.sql diff --git a/persistence-modules/spring-data-jpa-repo/README.md b/persistence-modules/spring-data-jpa-repo/README.md index f404263159..ffbd57d7f6 100644 --- a/persistence-modules/spring-data-jpa-repo/README.md +++ b/persistence-modules/spring-data-jpa-repo/README.md @@ -8,7 +8,6 @@ This module contains articles about repositories in Spring Data JPA - [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories) - [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories) - [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators) -- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) - [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries) - More articles: [[--> next]](../spring-data-jpa-repo-2) From a822f2ed0c84066042a8efbe43869791a2d27c23 Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Fri, 29 Mar 2024 16:11:09 +0530 Subject: [PATCH 40/92] JAVA-30993 Upgrade spring-boot-di, spring-boot-aws to spring-boot-3 (#16221) * JAVA-30993 Upgrade spring-boot-di, spring-boot-aws to spring-boot-3 * JAVA-30993 Revert maven shade plugin version upgrade --- spring-boot-modules/pom.xml | 4 ++-- spring-boot-modules/spring-boot-aws/pom.xml | 24 +++++++++++++++---- .../DisplayBeanIntegrationTest.java | 8 +++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 2b62b3d1bc..69b5e2b598 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -33,7 +33,7 @@ spring-boot-config-jpa-error spring-boot-ctx-fluent spring-boot-deployment - + spring-boot-di spring-boot-disable-logging spring-boot-ci-cd @@ -104,7 +104,7 @@ spring-boot-properties-3 spring-boot-properties-4 spring-boot-properties-migrator-demo - spring-boot-aws + spring-boot-aws spring-boot-keycloak-adapters spring-boot-mvc-legacy spring-boot-springdoc-2 diff --git a/spring-boot-modules/spring-boot-aws/pom.xml b/spring-boot-modules/spring-boot-aws/pom.xml index 44cd38be3f..8be0b230cd 100644 --- a/spring-boot-modules/spring-boot-aws/pom.xml +++ b/spring-boot-modules/spring-boot-aws/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.11 + 3.1.5 @@ -24,8 +24,21 @@ com.amazonaws.serverless - aws-serverless-java-container-springboot2 - ${aws-serverless-java-container-springboot2.version} + aws-serverless-java-container-springboot3 + ${aws-serverless-java-container.version} + + + com.amazonaws.serverless + aws-serverless-java-container-core + ${aws-serverless-java-container.version} + tests + test-jar + test + + + org.apache.httpcomponents.client5 + httpclient5 + ${httpclient5.version} org.springframework.boot @@ -74,10 +87,11 @@ - 1.9.1 - 3.2.4 + 2.0.0 + 3.3.0 11 11 + 5.3.1 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java b/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java index f08a755fc7..4e157e4e13 100644 --- a/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java +++ b/spring-boot-modules/spring-boot-di/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java @@ -13,10 +13,10 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.beans.BeansEndpoint.ContextBeans; +import org.springframework.boot.actuate.beans.BeansEndpoint.ContextBeansDescriptor; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -54,12 +54,12 @@ public class DisplayBeanIntegrationTest { @Test public void givenRestTemplate_whenAccessEndpointUrl_thenHttpStatusOK() throws Exception { - ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { }; RequestEntity requestEntity = RequestEntity.get(new URI("http://localhost:" + this.mgt + ACTUATOR_PATH + "/beans")) .accept(MediaType.APPLICATION_JSON) .build(); - ResponseEntity> entity = this.testRestTemplate.exchange(requestEntity, responseType); + ResponseEntity> entity = this.testRestTemplate.exchange(requestEntity, responseType); then(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } From 8711ec8f296d05dafd707c38fe96f77edeb890a0 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 29 Mar 2024 20:25:16 +0700 Subject: [PATCH 41/92] [JAVA-32058] Upgrade spring-rest-http-2, spring-rest-http-3 to Boot 3 (#16225) --- spring-web-modules/spring-rest-http-2/pom.xml | 5 +++-- .../src/main/java/com/baeldung/putvspost/Address.java | 6 +++--- .../java/com/baeldung/requesttimeout/domain/Book.java | 4 ++-- .../main/java/com/baeldung/unsupportedmediatype/User.java | 2 +- .../requesttimeout/RequestTimeoutIntegrationTest.java | 2 +- spring-web-modules/spring-rest-http-3/pom.xml | 8 ++++++-- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/spring-web-modules/spring-rest-http-2/pom.xml b/spring-web-modules/spring-rest-http-2/pom.xml index c6c8cd2010..588e121162 100644 --- a/spring-web-modules/spring-rest-http-2/pom.xml +++ b/spring-web-modules/spring-rest-http-2/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -53,6 +53,7 @@ 2.9.2 2.1.0 1.7.0 + com.baeldung.Main
\ No newline at end of file diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/putvspost/Address.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/putvspost/Address.java index 5c005c70f0..7c93b36b27 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/putvspost/Address.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/putvspost/Address.java @@ -1,8 +1,8 @@ package com.baeldung.putvspost; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; @Entity public class Address { diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/Book.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/Book.java index 846bfb2cec..710cafd175 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/Book.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/requesttimeout/domain/Book.java @@ -1,7 +1,7 @@ package com.baeldung.requesttimeout.domain; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; @Entity public class Book { diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/unsupportedmediatype/User.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/unsupportedmediatype/User.java index 765149dad5..4db6ae7bc9 100644 --- a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/unsupportedmediatype/User.java +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/unsupportedmediatype/User.java @@ -1,6 +1,6 @@ package com.baeldung.unsupportedmediatype; -import javax.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlRootElement; import java.io.Serializable; @XmlRootElement diff --git a/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java index d30dc351fa..6fd56bf89c 100644 --- a/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java +++ b/spring-web-modules/spring-rest-http-2/src/test/java/com/baeldung/requesttimeout/RequestTimeoutIntegrationTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; diff --git a/spring-web-modules/spring-rest-http-3/pom.xml b/spring-web-modules/spring-rest-http-3/pom.xml index 2de635c1f1..f9f9b35a3b 100644 --- a/spring-web-modules/spring-rest-http-3/pom.xml +++ b/spring-web-modules/spring-rest-http-3/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -26,4 +26,8 @@ + + com.baeldung.Main + + \ No newline at end of file From c15f637d3a7f12476aa8717a30c74e99469befb7 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 29 Mar 2024 21:12:29 +0700 Subject: [PATCH 42/92] [JAVA-30352] Move code of article Use Criteria Queries to spring-data-jpa-query-2 (#16230) --- .../java/com/baeldung/criteriaquery/Book.java | 57 +++++++++++++++++++ .../criteriaquery/BookRepository.java | 9 +++ .../criteriaquery/BookRepositoryCustom.java | 9 +++ .../criteriaquery/BookRepositoryImpl.java | 39 +++++++++++++ .../CriteriaQueryIntegrationTest.java | 50 ++++++++++++++++ 5 files changed, 164 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java create mode 100644 persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java create mode 100644 persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java create mode 100644 persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java create mode 100644 persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java new file mode 100644 index 0000000000..127b56ef0f --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/Book.java @@ -0,0 +1,57 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import org.springframework.data.jpa.domain.Specification; + +@Entity +public class Book { + + @Id + @GeneratedValue + private Long id; + private String title; + private String author; + + public Book(String title, String author) { + this.title = title; + this.author = author; + } + + public Book() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + static Specification hasAuthor(String author) { + return (book, cq, cb) -> cb.equal(book.get("author"), author); + } + + static Specification titleContains(String title) { + return (book, cq, cb) -> cb.like(book.get("title"), "%" + title + "%"); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java new file mode 100644 index 0000000000..61c47a1d85 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.criteriaquery; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +interface BookRepository extends JpaRepository, BookRepositoryCustom, JpaSpecificationExecutor { +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java new file mode 100644 index 0000000000..9863cb72a3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryCustom.java @@ -0,0 +1,9 @@ +package com.baeldung.criteriaquery; + +import java.util.List; + +interface BookRepositoryCustom { + + List findBooksByAuthorNameAndTitle(String authorName, String title); + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java new file mode 100644 index 0000000000..c227bf6e96 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/criteriaquery/BookRepositoryImpl.java @@ -0,0 +1,39 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class BookRepositoryImpl implements BookRepositoryCustom { + + @Autowired + private EntityManager em; + + @Override + public List findBooksByAuthorNameAndTitle(String authorName, String title) { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Book.class); + + Root book = cq.from(Book.class); + List predicates = new ArrayList<>(); + + if (authorName != null) { + predicates.add(cb.equal(book.get("author"), authorName)); + } + if (title != null) { + predicates.add(cb.like(book.get("title"), "%" + title + "%")); + } + cq.where(predicates.toArray(new Predicate[0])); + + return em.createQuery(cq).getResultList(); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java new file mode 100644 index 0000000000..5f28b01997 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/criteriaquery/CriteriaQueryIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.criteriaquery; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static com.baeldung.criteriaquery.Book.hasAuthor; +import static com.baeldung.criteriaquery.Book.titleContains; +import static org.junit.Assert.assertEquals; +import static org.springframework.data.jpa.domain.Specification.where; + +@DataJpaTest(showSql = false) +@RunWith(SpringRunner.class) +public class CriteriaQueryIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private BookRepository repository; + + @Before + public void before() { + entityManager.persist(new Book("title1", "author1")); + entityManager.persist(new Book("title2", "author2")); + } + + @Test + public void givenAuthorAndTextInTitle_whenFindWithSpecification_ThenFound() { + List books = repository.findAll(where(hasAuthor("author1")).and(titleContains("1"))); + assertEquals(1, books.size()); + assertEquals("author1", books.get(0).getAuthor()); + assertEquals("title1", books.get(0).getTitle()); + } + + @Test + public void givenAuthorAndTextInTitle_whenFindWithCriteriaQuery_ThenFound() { + List books = repository.findBooksByAuthorNameAndTitle("author2", "2"); + assertEquals(1, books.size()); + assertEquals("author2", books.get(0).getAuthor()); + assertEquals("title2", books.get(0).getTitle()); + } + +} From b7b1e2be2304738f8bab6bf5ee8a7ac9069d2cce Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 29 Mar 2024 20:36:33 +0200 Subject: [PATCH 43/92] JAVA-25483 add global logback config (#15829) --- libraries-server/pom.xml | 1 + logback-config.xml => logback-config-global.xml | 0 pom.xml | 17 +++++------------ 3 files changed, 6 insertions(+), 12 deletions(-) rename logback-config.xml => logback-config-global.xml (100%) diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index 66d6295f7c..bb1ffb1e49 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -97,6 +97,7 @@ 4.3.1 1.2.0 2.3.1 + logback.xml
\ No newline at end of file diff --git a/logback-config.xml b/logback-config-global.xml similarity index 100% rename from logback-config.xml rename to logback-config-global.xml diff --git a/pom.xml b/pom.xml index c56d7d4c13..d9c7e439b8 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,9 @@ **/JdbcTest.java **/*LiveTest.java + + ${tutorialsproject.basedir}/${logback.configurationFileName} + @@ -318,9 +321,6 @@ **/JdbcTest.java **/*LiveTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -388,9 +388,6 @@ **/*JdbcTest.java **/*LiveTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -471,9 +468,6 @@ **/*IntegrationTest.java **/*IntTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -530,9 +524,6 @@ **/*IntegrationTest.java **/*IntTest.java - - ${tutorialsproject.basedir}/logback-config.xml - @@ -1198,6 +1189,8 @@ 2.1.214 33.0.0-jre 3.3.0 + + logback-config-global.xml From 96c992cd8777e1d3356e3caa69e6ac9a2a5ee5dd Mon Sep 17 00:00:00 2001 From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com> Date: Sat, 30 Mar 2024 12:38:38 +0100 Subject: [PATCH 44/92] BAEL-7703: Update article "Converting Between Byte Arrays and Hexadecimal Strings in Java" (#16271) --- .../algorithms-miscellaneous-5/pom.xml | 12 +++++++ .../conversion/HexStringConverter.java | 21 ++++++++---- .../ByteArrayConverterUnitTest.java | 32 +++++++++++++------ 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/algorithms-modules/algorithms-miscellaneous-5/pom.xml b/algorithms-modules/algorithms-miscellaneous-5/pom.xml index c1739e3690..2d95bf2a01 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/pom.xml +++ b/algorithms-modules/algorithms-miscellaneous-5/pom.xml @@ -5,6 +5,18 @@ 4.0.0 algorithms-miscellaneous-5 0.0.1-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + algorithms-miscellaneous-5 diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java index ae434d88ad..5e4b35bfaf 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java @@ -1,15 +1,12 @@ package com.baeldung.algorithms.conversion; -import java.math.BigInteger; - - - +import com.google.common.io.BaseEncoding; +import jakarta.xml.bind.DatatypeConverter; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; -import com.google.common.io.BaseEncoding; - -import jakarta.xml.bind.DatatypeConverter; +import java.math.BigInteger; +import java.util.HexFormat; public class HexStringConverter { @@ -109,4 +106,14 @@ public class HexStringConverter { return BaseEncoding.base16() .decode(hexString.toUpperCase()); } + + public String encodeUsingHexFormat(byte[] bytes) { + HexFormat hexFormat = HexFormat.of(); + return hexFormat.formatHex(bytes); + } + + public byte[] decodeUsingHexFormat(String hexString) { + HexFormat hexFormat = HexFormat.of(); + return hexFormat.parseHex(hexString); + } } diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java b/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java index bb344e8b30..ee003ffac7 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java @@ -1,15 +1,13 @@ package com.baeldung.algorithms.conversion; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - import org.apache.commons.codec.DecoderException; import org.hamcrest.text.IsEqualIgnoringCase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.baeldung.algorithms.conversion.HexStringConverter; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class ByteArrayConverterUnitTest { @@ -24,7 +22,7 @@ class ByteArrayConverterUnitTest { void shouldEncodeByteArrayToHexStringUsingBigIntegerToString() { byte[] bytes = getSampleBytes(); String hexString = getSampleHexString(); - if(hexString.charAt(0) == '0') { + if (hexString.charAt(0) == '0') { hexString = hexString.substring(1); } String output = hexStringConverter.encodeUsingBigIntegerToString(bytes); @@ -46,7 +44,7 @@ class ByteArrayConverterUnitTest { byte[] output = hexStringConverter.decodeUsingBigInteger(hexString); assertArrayEquals(bytes, output); } - + @Test void shouldEncodeByteArrayToHexStringUsingCharacterConversion() { byte[] bytes = getSampleBytes(); @@ -62,7 +60,7 @@ class ByteArrayConverterUnitTest { byte[] output = hexStringConverter.decodeHexString(hexString); assertArrayEquals(bytes, output); } - + @Test void shouldDecodeHexToByteWithInvalidHexCharacter() { assertThrows(IllegalArgumentException.class, () -> { @@ -118,12 +116,28 @@ class ByteArrayConverterUnitTest { assertArrayEquals(bytes, output); } + @Test + void shouldEncodeByteArrayToHexStringUsingHexFormat() throws DecoderException { + byte[] bytes = getSampleBytes(); + String hexString = getSampleHexString(); + String output = hexStringConverter.encodeUsingHexFormat(bytes); + assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString)); + } + + @Test + void shouldDecodeHexStringToByteArrayUsingHexFormat() throws DecoderException { + byte[] bytes = getSampleBytes(); + String hexString = getSampleHexString(); + byte[] output = hexStringConverter.decodeUsingHexFormat(hexString); + assertArrayEquals(bytes, output); + } + private String getSampleHexString() { return "0af50c0e2d10"; } private byte[] getSampleBytes() { - return new byte[] { 10, -11, 12, 14, 45, 16 }; + return new byte[]{10, -11, 12, 14, 45, 16}; } } From 404c3bf5733f9bc4be416786bda69a63b58978f3 Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Sat, 30 Mar 2024 13:48:24 +0200 Subject: [PATCH 45/92] JAVA-31643 Upgrade spring-boot-request-params, spring-boot-3-native and spring-boot-redis (#16254) Co-authored-by: timis1 --- spring-boot-modules/pom.xml | 4 ++-- .../springbootredis/config/RedisTestConfiguration.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 69b5e2b598..6bb955c657 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -88,12 +88,12 @@ spring-boot-data-2 spring-boot-validation - + spring-boot-redis spring-boot-cassandre spring-boot-react spring-boot-3-grpc - + spring-boot-3-native spring-boot-3-observation spring-boot-3-test-pitfalls spring-boot-3-testcontainers diff --git a/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java b/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java index 6fbd140981..8f59c5bd65 100644 --- a/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java +++ b/spring-boot-modules/spring-boot-redis/src/test/java/com/baelding/springbootredis/config/RedisTestConfiguration.java @@ -13,6 +13,11 @@ public class RedisTestConfiguration { public RedisTestConfiguration(RedisProperties redisProperties) { this.redisServer = new RedisServer(redisProperties.getPort()); + // To run on windows uncomment the following lines + // this.redisServer = RedisServer.builder().setting("maxheap 200m") + // .port(redisProperties.getPort()) + // .setting("bind localhost") + // .build(); } @PostConstruct From 6ff926e003358723afb8c5be8a9351047cc5d8ed Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Sat, 30 Mar 2024 19:42:52 +0200 Subject: [PATCH 46/92] JAVA-32053 Upgrade spring-mvc-basics-3 to Spring Boot 3 (#16231) Co-authored-by: timis1 --- .../spring-mvc-basics-3/pom.xml | 13 ++++------ .../java/com/baeldung/boot/Application.java | 4 +--- .../controller/GenericEntityController.java | 2 +- .../converter/GenericBigDecimalConverter.java | 2 +- .../com/baeldung/boot/domain/Employee.java | 4 ++-- .../java/com/baeldung/boot/domain/Foo.java | 3 ++- .../baeldung/boot/domain/GenericEntity.java | 8 +++---- .../HeaderVersionArgumentResolver.java | 2 +- .../CachedBodyHttpServletRequest.java | 6 ++--- .../CachedBodyServletInputStream.java | 4 ++-- .../cachedrequest/ContentCachingFilter.java | 10 ++++---- .../cachedrequest/HttpRequestDemoConfig.java | 4 +--- .../PrintRequestContentFilter.java | 13 +++++----- .../ContactNumberConstraint.java | 4 ++-- .../ContactNumberValidator.java | 4 ++-- .../customvalidator/FieldsValueMatch.java | 4 ++-- .../FieldsValueMatchValidator.java | 4 ++-- .../customvalidator/NewUserController.java | 2 +- .../ValidatedPhoneController.java | 2 +- .../controllers/PoemSubmission.java | 2 +- .../interpolation/MyMessageInterpolator.java | 6 +---- .../interpolation/NotNullRequest.java | 2 +- .../interpolation/ValidationController.java | 2 +- .../interpolation/ValidationExamples.java | 9 +++---- .../controller/ReadHeaderRestController.java | 24 ++++++++----------- .../SpringBootMailIntegrationTest.java | 16 ++++++------- .../CachedBodyServletInputStreamUnitTest.java | 6 ++--- .../ContentCachingFilterUnitTest.java | 4 ++-- .../PrintRequestContentFilterUnitTest.java | 4 ++-- 29 files changed, 75 insertions(+), 95 deletions(-) diff --git a/spring-web-modules/spring-mvc-basics-3/pom.xml b/spring-web-modules/spring-mvc-basics-3/pom.xml index 7e0d741619..b38c1a493d 100644 --- a/spring-web-modules/spring-mvc-basics-3/pom.xml +++ b/spring-web-modules/spring-mvc-basics-3/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -51,18 +51,13 @@ h2 runtime - - javax.persistence - javax.persistence-api - ${jpa.version} - com.google.guava guava ${guava.version} - org.subethamail + com.github.davidmoten subethasmtp ${subethasmtp.version} test @@ -130,7 +125,7 @@ 3.1.1 3.3.7-1 2.2 - 3.1.7 + 7.0.2 4.5.8 diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java index cb0d0c1532..a78bb0410b 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java @@ -2,13 +2,11 @@ package com.baeldung.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ApplicationContext; @SpringBootApplication public class Application { - private static ApplicationContext applicationContext; public static void main(String[] args) { - applicationContext = SpringApplication.run(Application.class, args); + SpringApplication.run(Application.class, args); } } diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java index 39fd5af318..fdfe005518 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java @@ -53,6 +53,6 @@ public class GenericEntityController { @GetMapping("/entity/findbyversion") public ResponseEntity findByVersion(@Version String version) { - return version != null ? new ResponseEntity(entityList.stream().findFirst().get(), HttpStatus.OK) : new ResponseEntity(HttpStatus.NOT_FOUND); + return version != null ? new ResponseEntity<>(entityList.stream().findFirst().get(), HttpStatus.OK) : new ResponseEntity<>(HttpStatus.NOT_FOUND); } } diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java index 0040327e00..022b03ff0d 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java @@ -27,7 +27,7 @@ public class GenericBigDecimalConverter implements GenericConverter { return new BigDecimal(number); } else { Number number = (Number) source; - BigDecimal converted = new BigDecimal(number.doubleValue()); + BigDecimal converted = BigDecimal.valueOf(number.doubleValue()); return converted.setScale(2, BigDecimal.ROUND_HALF_EVEN); } } diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java index a96fc5d051..22a28b9fd7 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java @@ -1,7 +1,7 @@ package com.baeldung.boot.domain; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; @Entity public class Employee { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java index c6637f6162..26fbe54921 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java @@ -1,6 +1,7 @@ package com.baeldung.boot.domain; -import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; +import static org.thymeleaf.util.StringUtils.randomAlphanumeric; + public class Foo extends AbstractEntity { private String name; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java index a2a676200a..ba38aadeef 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java @@ -1,9 +1,9 @@ package com.baeldung.boot.domain; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; @Entity public class GenericEntity { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java index de10fa5098..8b012432ed 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java @@ -7,7 +7,7 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @Component public class HeaderVersionArgumentResolver implements HandlerMethodArgumentResolver { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java index 89acbe79a4..9e79b5fa42 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java @@ -6,9 +6,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; import org.springframework.util.StreamUtils; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java index 4d44b23ee9..6ae681d088 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java @@ -4,8 +4,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; public class CachedBodyServletInputStream extends ServletInputStream { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java index ba3901077b..75c73b509c 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java @@ -2,11 +2,11 @@ package com.baeldung.cachedrequest; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java index 9516ff861e..6e40540d01 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java @@ -5,10 +5,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** - * To initialize the WebApplication, Please see - * {@link com.baeldung.spring.config.MainWebAppInitializer} + * To initialize the WebApplication */ - @EnableWebMvc @Configuration @ComponentScan(basePackages = "com.baeldung.cachedrequest") diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java index 9c4c589a5d..bf1de0573f 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java @@ -4,19 +4,18 @@ package com.baeldung.cachedrequest; import java.io.IOException; import java.io.InputStream; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; -import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StreamUtils; import org.springframework.web.filter.OncePerRequestFilter; -@Order(Ordered.LOWEST_PRECEDENCE) +@Order @Component @WebFilter(filterName = "printRequestContentFilter", urlPatterns = "/*") public class PrintRequestContentFilter extends OncePerRequestFilter { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java index 42e441f8f9..525c1096a1 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java @@ -6,8 +6,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; @Documented @Constraint(validatedBy = ContactNumberValidator.class) diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java index fe14f3ccf1..6436bef8fd 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java @@ -1,7 +1,7 @@ package com.baeldung.customvalidator; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class ContactNumberValidator implements ConstraintValidator { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java index 51db279f0b..2714f2cdef 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java @@ -5,8 +5,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; @Constraint(validatedBy = FieldsValueMatchValidator.class) @Target({ ElementType.TYPE }) diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java index c3e8533ec9..e807a9b649 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java @@ -1,7 +1,7 @@ package com.baeldung.customvalidator; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import org.springframework.beans.BeanWrapperImpl; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/NewUserController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/NewUserController.java index 040dcf1a85..27aac68adc 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/NewUserController.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/NewUserController.java @@ -1,6 +1,6 @@ package com.baeldung.customvalidator; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java index be347a6777..9f23c5b14d 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/customvalidator/ValidatedPhoneController.java @@ -1,6 +1,6 @@ package com.baeldung.customvalidator; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java index 6264ea0531..c37a26749d 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java @@ -11,7 +11,7 @@ import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.servlet.view.RedirectView; import java.util.Map; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @Controller public class PoemSubmission { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java index efa3d62b88..c5a2fc868a 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java @@ -1,14 +1,10 @@ package com.baeldung.interpolation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import javax.validation.MessageInterpolator; +import jakarta.validation.MessageInterpolator; import java.util.Locale; public class MyMessageInterpolator implements MessageInterpolator { - private static Logger logger = LoggerFactory.getLogger(MyMessageInterpolator.class); - private final MessageInterpolator defaultInterpolator; public MyMessageInterpolator(MessageInterpolator interpolator) { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java index 9a2b00be8f..2bf1e2e45a 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java @@ -1,6 +1,6 @@ package com.baeldung.interpolation; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; public class NotNullRequest { diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java index 3fed170fdf..5637d2eba2 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java @@ -1,6 +1,6 @@ package com.baeldung.interpolation; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java index 6c9b924200..53d3e577c8 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java @@ -1,14 +1,11 @@ package com.baeldung.interpolation; -import java.util.Formatter; -import javax.validation.constraints.Size; -import javax.validation.constraints.Min; -import javax.validation.constraints.DecimalMin; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; public class ValidationExamples { - private static final Formatter formatter = new Formatter(); - @Size( min = 5, max = 14, diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java index ff4d0eea58..7106b3f5bc 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java @@ -22,7 +22,7 @@ public class ReadHeaderRestController { @GetMapping("/") public ResponseEntity index() { - return new ResponseEntity("Index", HttpStatus.OK); + return new ResponseEntity<>("Index", HttpStatus.OK); } @GetMapping("/greeting") @@ -46,12 +46,12 @@ public class ReadHeaderRestController { break; } - return new ResponseEntity(greeting, HttpStatus.OK); + return new ResponseEntity<>(greeting, HttpStatus.OK); } @GetMapping("/double") public ResponseEntity doubleNumber(@RequestHeader("my-number") int myNumber) { - return new ResponseEntity( + return new ResponseEntity<>( String.format("%d * 2 = %d", myNumber, (myNumber * 2)), HttpStatus.OK); } @@ -59,34 +59,30 @@ public class ReadHeaderRestController { @GetMapping("/listHeaders") public ResponseEntity listAllHeaders(@RequestHeader Map headers) { - headers.forEach((key, value) -> { - LOG.info(String.format("Header '%s' = %s", key, value)); - }); + headers.forEach((key, value) -> LOG.info(String.format("Header '%s' = %s", key, value))); - return new ResponseEntity(String.format("Listed %d headers", headers.size()), HttpStatus.OK); + return new ResponseEntity<>(String.format("Listed %d headers", headers.size()), HttpStatus.OK); } @GetMapping("/multiValue") public ResponseEntity multiValue(@RequestHeader MultiValueMap headers) { - headers.forEach((key, value) -> { - LOG.info(String.format("Header '%s' = %s", key, value.stream().collect(Collectors.joining("|")))); - }); + headers.forEach((key, value) -> LOG.info(String.format("Header '%s' = %s", key, String.join("|", value)))); - return new ResponseEntity(String.format("Listed %d headers", headers.size()), HttpStatus.OK); + return new ResponseEntity<>(String.format("Listed %d headers", headers.size()), HttpStatus.OK); } @GetMapping("/getBaseUrl") public ResponseEntity getBaseUrl(@RequestHeader HttpHeaders headers) { InetSocketAddress host = headers.getHost(); String url = "http://" + host.getHostName() + ":" + host.getPort(); - return new ResponseEntity(String.format("Base URL = %s", url), HttpStatus.OK); + return new ResponseEntity<>(String.format("Base URL = %s", url), HttpStatus.OK); } @GetMapping("/nonRequiredHeader") public ResponseEntity evaluateNonRequiredHeader( @RequestHeader(value = "optional-header", required = false) String optionalHeader) { - return new ResponseEntity( + return new ResponseEntity<>( String.format("Was the optional header present? %s!", (optionalHeader == null ? "No" : "Yes")), HttpStatus.OK); } @@ -95,6 +91,6 @@ public class ReadHeaderRestController { public ResponseEntity evaluateDefaultHeaderValue( @RequestHeader(value = "optional-header", defaultValue = "3600") int optionalHeader) { - return new ResponseEntity(String.format("Optional Header is %d", optionalHeader), HttpStatus.OK); + return new ResponseEntity<>(String.format("Optional Header is %d", optionalHeader), HttpStatus.OK); } } diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java index 1349e7e9e0..4d4ac784b3 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.subethamail.wiser.Wiser; import org.subethamail.wiser.WiserMessage; -import javax.mail.MessagingException; +import jakarta.mail.MessagingException; import java.io.IOException; import java.util.List; @@ -29,20 +29,20 @@ public class SpringBootMailIntegrationTest { private Wiser wiser; - private String userTo = "user2@localhost"; - private String userFrom = "user1@localhost"; - private String subject = "Test subject"; - private String textMail = "Text subject mail"; + private final String userTo = "user2@localhost"; + private final String userFrom = "user1@localhost"; + private final String subject = "Test subject"; + private final String textMail = "Text subject mail"; @Before - public void setUp() throws Exception { + public void setUp() { final int TEST_PORT = 8025; - wiser = new Wiser(TEST_PORT); + wiser = Wiser.port(TEST_PORT); wiser.start(); } @After - public void tearDown() throws Exception { + public void tearDown() { wiser.stop(); } diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java index af025f632e..21f8854bdf 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java @@ -3,7 +3,7 @@ package com.baeldung.cachedrequest; import java.io.ByteArrayOutputStream; import java.io.IOException; -import javax.servlet.ReadListener; +import jakarta.servlet.ReadListener; import org.junit.After; import org.junit.Test; @@ -54,7 +54,7 @@ public class CachedBodyServletInputStreamUnitTest extends TestCase { } @Test - public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledIsReady_ThenTrue() throws IOException { + public void testGivenServletInputStreamCreatedAndBodyRead_whenCalledIsReady_ThenTrue() { // Given byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes(); servletInputStream = new CachedBodyServletInputStream(cachedBody); @@ -85,7 +85,7 @@ public class CachedBodyServletInputStreamUnitTest extends TestCase { } @Test(expected = UnsupportedOperationException.class) - public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenThrowsException() throws IOException { + public void testGivenServletInputStreamCreated_whenCalledIsRead_ThenThrowsException() { // Given byte[] cachedBody = "{\"firstName\" :\"abc\",\"lastName\" : \"xyz\",\"age\" : 30\"}".getBytes(); servletInputStream = new CachedBodyServletInputStream(cachedBody); diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java index ec0f8948c2..26c3fd37a0 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java @@ -2,8 +2,8 @@ package com.baeldung.cachedrequest; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java index 3d2acabe6b..b694c5220b 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java @@ -2,8 +2,8 @@ package com.baeldung.cachedrequest; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; import org.junit.Test; import org.junit.runner.RunWith; From 39f3c493ac0417ffe4b4545bcfcf0ad52924aee6 Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:51:01 +0200 Subject: [PATCH 47/92] JAVA-32054 Upgrade spring-mvc-file to Spring Boot 3 (#16218) --- spring-web-modules/spring-mvc-file/pom.xml | 23 ++----------------- .../baeldung/file/CustomMultipartFile.java | 4 ++-- .../file/CustomMultipartFileUnitTest.java | 8 +++---- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/spring-web-modules/spring-mvc-file/pom.xml b/spring-web-modules/spring-mvc-file/pom.xml index c6b063c785..b596e5380e 100644 --- a/spring-web-modules/spring-mvc-file/pom.xml +++ b/spring-web-modules/spring-mvc-file/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -25,26 +25,7 @@ spring-boot-starter-test test - - commons-io - commons-io - ${commons-io.version} - - - spring-mvc-file - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.Application - JAR - - - - - \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-file/src/main/java/com/baeldung/file/CustomMultipartFile.java b/spring-web-modules/spring-mvc-file/src/main/java/com/baeldung/file/CustomMultipartFile.java index c68729588f..3ad1fbbea4 100644 --- a/spring-web-modules/spring-mvc-file/src/main/java/com/baeldung/file/CustomMultipartFile.java +++ b/spring-web-modules/spring-mvc-file/src/main/java/com/baeldung/file/CustomMultipartFile.java @@ -41,12 +41,12 @@ public class CustomMultipartFile implements MultipartFile { } @Override - public byte[] getBytes() throws IOException { + public byte[] getBytes() { return input; } @Override - public InputStream getInputStream() throws IOException { + public InputStream getInputStream() { return new ByteArrayInputStream(input); } diff --git a/spring-web-modules/spring-mvc-file/src/test/java/com/baeldung/file/CustomMultipartFileUnitTest.java b/spring-web-modules/spring-mvc-file/src/test/java/com/baeldung/file/CustomMultipartFileUnitTest.java index 1aa07766ca..295fb92c0f 100644 --- a/spring-web-modules/spring-mvc-file/src/test/java/com/baeldung/file/CustomMultipartFileUnitTest.java +++ b/spring-web-modules/spring-mvc-file/src/test/java/com/baeldung/file/CustomMultipartFileUnitTest.java @@ -9,7 +9,7 @@ import org.springframework.mock.web.MockMultipartFile; class CustomMultipartFileUnitTest { @Test - void whenProvidingByteArray_thenMultipartFileCreated() throws IOException { + void whenProvidingByteArray_thenMultipartFileCreated() { byte[] inputArray = "Test String".getBytes(); CustomMultipartFile customMultipartFile = new CustomMultipartFile(inputArray); Assertions.assertFalse(customMultipartFile.isEmpty()); @@ -18,21 +18,21 @@ class CustomMultipartFileUnitTest { } @Test - void whenProvidingEmptyByteArray_thenMockMultipartFileIsEmpty() throws IOException { + void whenProvidingEmptyByteArray_thenMockMultipartFileIsEmpty() { byte[] inputArray = "".getBytes(); MockMultipartFile mockMultipartFile = new MockMultipartFile("tempFileName", inputArray); Assertions.assertTrue(mockMultipartFile.isEmpty()); } @Test - void whenProvidingNullByteArray_thenMockMultipartFileIsEmpty() throws IOException { + void whenProvidingNullByteArray_thenMockMultipartFileIsEmpty() { byte[] inputArray = null; MockMultipartFile mockMultipartFile = new MockMultipartFile("tempFileName", inputArray); Assertions.assertTrue(mockMultipartFile.isEmpty()); } @Test - void whenProvidingByteArray_thenMultipartFileInputSizeMatches() throws IOException { + void whenProvidingByteArray_thenMultipartFileInputSizeMatches() { byte[] inputArray = "Testing String".getBytes(); CustomMultipartFile customMultipartFile = new CustomMultipartFile(inputArray); Assertions.assertEquals(inputArray.length, customMultipartFile.getSize()); From 6f8b90830e5911b83a850f6232cf66b089371b49 Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sat, 30 Mar 2024 22:44:48 +0100 Subject: [PATCH 48/92] [static-injection] improvement --- .../staticvalue/injection/Application.java | 17 ----------- .../injection/PropertyController.java | 30 ------------------- .../StaticPropertyHolder.java | 26 ++++++++++++++++ .../src/main/resources/application.properties | 2 +- .../StaticPropertyHolderUnitTest.java | 18 +++++++++++ 5 files changed, 45 insertions(+), 48 deletions(-) delete mode 100644 spring-di-2/src/main/java/com/baeldung/staticvalue/injection/Application.java delete mode 100644 spring-di-2/src/main/java/com/baeldung/staticvalue/injection/PropertyController.java create mode 100644 spring-di-2/src/main/java/com/baeldung/staticvalueinjection/StaticPropertyHolder.java create mode 100644 spring-di-2/src/test/java/com/baeldung/staticvalueinjection/StaticPropertyHolderUnitTest.java diff --git a/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/Application.java b/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/Application.java deleted file mode 100644 index b4222ddcc9..0000000000 --- a/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/Application.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.staticvalue.injection; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) -@PropertySource("/application.properties") - -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} diff --git a/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/PropertyController.java b/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/PropertyController.java deleted file mode 100644 index f5910ea4f8..0000000000 --- a/spring-di-2/src/main/java/com/baeldung/staticvalue/injection/PropertyController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.staticvalue.injection; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Arrays; -import java.util.List; - -@RestController -public class PropertyController { - - @Value("${name}") - private String name; - - @Value("${name}") - private static String NAME_NULL; - - private static String NAME_STATIC; - - @Value("${name}") - public void setNameStatic(String name){ - PropertyController.NAME_STATIC = name; - } - - @GetMapping("/properties") - public List getProperties(){ - return Arrays.asList(this.name, NAME_STATIC, NAME_NULL) ; - } -} diff --git a/spring-di-2/src/main/java/com/baeldung/staticvalueinjection/StaticPropertyHolder.java b/spring-di-2/src/main/java/com/baeldung/staticvalueinjection/StaticPropertyHolder.java new file mode 100644 index 0000000000..4d9911eef1 --- /dev/null +++ b/spring-di-2/src/main/java/com/baeldung/staticvalueinjection/StaticPropertyHolder.java @@ -0,0 +1,26 @@ +package com.baeldung.staticvalueinjection; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class StaticPropertyHolder { + + @Value("${name}") + private static String STATIC_NAME_INJECTED_ON_FIELD; + + private static String STATIC_NAME; + + @Value("${name}") + public void setStaticName(String name) { + STATIC_NAME = name; + } + + public static String getStaticName() { + return STATIC_NAME; + } + + public static String getStaticNameInjectedOnField() { + return STATIC_NAME_INJECTED_ON_FIELD; + } +} \ No newline at end of file diff --git a/spring-di-2/src/main/resources/application.properties b/spring-di-2/src/main/resources/application.properties index 828fa9cd2a..32eff61207 100644 --- a/spring-di-2/src/main/resources/application.properties +++ b/spring-di-2/src/main/resources/application.properties @@ -1 +1 @@ -name = Inject a value to a static field +name = Inject a value to a static field \ No newline at end of file diff --git a/spring-di-2/src/test/java/com/baeldung/staticvalueinjection/StaticPropertyHolderUnitTest.java b/spring-di-2/src/test/java/com/baeldung/staticvalueinjection/StaticPropertyHolderUnitTest.java new file mode 100644 index 0000000000..4e73ff56b9 --- /dev/null +++ b/spring-di-2/src/test/java/com/baeldung/staticvalueinjection/StaticPropertyHolderUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.staticvalueinjection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = StaticPropertyHolder.class) +public class StaticPropertyHolderUnitTest { + + @Test + public void givenStaticPropertyInSpringBean_WhenUsingValueOnSetter_ThenValueInjected() { + assertNull(StaticPropertyHolder.getStaticNameInjectedOnField()); + assertEquals("Inject a value to a static field", StaticPropertyHolder.getStaticName()); + } + +} \ No newline at end of file From ff723063a709cd6983cc35bc1302112c43f2c2f0 Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Sun, 31 Mar 2024 22:38:53 +0300 Subject: [PATCH 49/92] JAVA-31002 Upgrade spring-boot-swagger (#16244) Co-authored-by: timis1 --- spring-boot-modules/pom.xml | 2 +- spring-boot-modules/spring-boot-swagger/pom.xml | 14 +++++++++++--- .../swaggerenums/controller/HireController.java | 6 +++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 6bb955c657..9b8a3b318a 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -75,7 +75,7 @@ spring-boot-ssl-bundles spring-boot-telegram spring-boot-springdoc - + spring-boot-swagger spring-boot-swagger-jwt spring-boot-swagger-keycloak diff --git a/spring-boot-modules/spring-boot-swagger/pom.xml b/spring-boot-modules/spring-boot-swagger/pom.xml index 668c9d561f..bd74c3ea88 100644 --- a/spring-boot-modules/spring-boot-swagger/pom.xml +++ b/spring-boot-modules/spring-boot-swagger/pom.xml @@ -10,9 +10,10 @@ Module For Spring Boot Swagger - com.baeldung.spring-boot-modules - spring-boot-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + ../../parent-boot-3 + 0.0.1-SNAPSHOT @@ -30,6 +31,11 @@ springdoc-openapi-ui ${springdoc.version} + + jakarta.ws.rs + jakarta.ws.rs-api + ${jakarta.ws.rs-api.version} + @@ -82,6 +88,8 @@ 3.1.1 1.7.0 + 3.1.0 + com.baeldung.swaggerexample.SwaggerExampleApplication \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java index 7b7bfdc2c5..9b142d3802 100644 --- a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/swaggerenums/controller/HireController.java @@ -5,9 +5,9 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; @Api @Path(value="/hire") From 25217a11bda7ec83e6b5f39c22cde0fb6a8ce91b Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Mon, 1 Apr 2024 15:30:57 +0530 Subject: [PATCH 50/92] JAVA-29183 :- Upgrade spring-5-webflux & spring-5-webflux-2 to Spring Boot 3. (#16149) Co-authored-by: Amit Pandey --- spring-5-webflux-2/pom.xml | 34 +++---------------- .../src/main/resources/logback.xml | 11 +++--- .../src/test/resources/logback-test.xml | 7 ---- spring-5-webflux/pom.xml | 14 ++++++-- .../ResponseStatusController.java | 6 ++-- .../spring/retry/ExternalConnector.java | 3 +- .../NettyWebServerFactorySslCustomizer.java | 2 +- .../serverconfig/TimeoutController.java | 2 +- .../src/main/resources/logback.xml | 11 +++--- .../src/test/resources/logback-test.xml | 9 +++-- 10 files changed, 36 insertions(+), 63 deletions(-) diff --git a/spring-5-webflux-2/pom.xml b/spring-5-webflux-2/pom.xml index 38cbbc8bf0..2bc981f9db 100644 --- a/spring-5-webflux-2/pom.xml +++ b/spring-5-webflux-2/pom.xml @@ -10,30 +10,11 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 - - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - - org.springframework.boot @@ -110,14 +91,6 @@ org.springframework.boot spring-boot-maven-plugin - - org.apache.maven.plugins - maven-compiler-plugin - - 16 - 16 - - @@ -126,6 +99,9 @@ 3.1.8 1.16.2 5.0.0-alpha.12 + true + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-5-webflux-2/src/main/resources/logback.xml b/spring-5-webflux-2/src/main/resources/logback.xml index 48b68c6bf1..a81845477f 100644 --- a/spring-5-webflux-2/src/main/resources/logback.xml +++ b/spring-5-webflux-2/src/main/resources/logback.xml @@ -1,12 +1,9 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + diff --git a/spring-5-webflux-2/src/test/resources/logback-test.xml b/spring-5-webflux-2/src/test/resources/logback-test.xml index 12cedf5952..254798dc62 100644 --- a/spring-5-webflux-2/src/test/resources/logback-test.xml +++ b/spring-5-webflux-2/src/test/resources/logback-test.xml @@ -1,12 +1,5 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - - diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index 62a463a5cd..f0de0e5dcb 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -90,12 +90,22 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + + true + + 5.0.0-alpha.12 2.0.0-Beta4 + true + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java index bc4f628ab1..121608e7c2 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java @@ -18,18 +18,18 @@ import static org.springframework.web.reactive.function.server.RequestPredicates @RestController public class ResponseStatusController { - @GetMapping(value = "/ok", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/ok", produces = MediaType.APPLICATION_JSON_VALUE) public Flux ok() { return Flux.just("ok"); } - @GetMapping(value = "/no-content", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/no-content", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.NO_CONTENT) public Flux noContent() { return Flux.empty(); } - @GetMapping(value = "/accepted", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @GetMapping(value = "/accepted", produces = MediaType.APPLICATION_JSON_VALUE) public Flux accepted(ServerHttpResponse response) { response.setStatusCode(HttpStatus.ACCEPTED); return Flux.just("accepted"); diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java b/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java index baace095a7..597831b7e6 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/retry/ExternalConnector.java @@ -3,6 +3,7 @@ package com.baeldung.spring.retry; import java.time.Duration; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -24,7 +25,7 @@ public class ExternalConnector { .uri(PATH_BY_ID, stockId) .accept(MediaType.APPLICATION_JSON) .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new ServiceException("Server error", response.rawStatusCode()))) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.error(new ServiceException("Server error", response.statusCode().value()))) .bodyToMono(String.class) .retryWhen(Retry.backoff(3, Duration.ofSeconds(2)) .filter(throwable -> throwable instanceof ServiceException) diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java index cf4e5ac8ea..9ee722cb55 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java @@ -20,7 +20,7 @@ public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCusto ssl.setKeyStorePassword("secret"); Http2 http2 = new Http2(); http2.setEnabled(false); - serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null)); + serverFactory.addServerCustomizers(new SslServerCustomizer(http2, ssl.getClientAuth(), null)); serverFactory.setPort(8443); } } diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java index a4cd6bd6ba..3f0c004d6c 100644 --- a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/TimeoutController.java @@ -14,7 +14,7 @@ public class TimeoutController { @GetMapping("/{timeout}") private Mono timeout(@PathVariable int timeout) { try { - Thread.sleep(timeout * 1000); + Thread.sleep(timeout * 1000L); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } diff --git a/spring-5-webflux/src/main/resources/logback.xml b/spring-5-webflux/src/main/resources/logback.xml index 48b68c6bf1..a81845477f 100644 --- a/spring-5-webflux/src/main/resources/logback.xml +++ b/spring-5-webflux/src/main/resources/logback.xml @@ -1,12 +1,9 @@ - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + diff --git a/spring-5-webflux/src/test/resources/logback-test.xml b/spring-5-webflux/src/test/resources/logback-test.xml index 12cedf5952..c1df08bdb5 100644 --- a/spring-5-webflux/src/test/resources/logback-test.xml +++ b/spring-5-webflux/src/test/resources/logback-test.xml @@ -1,12 +1,11 @@ - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %kvp%n + + From c2684009bc314688d90716c099609d65f1e5de0d Mon Sep 17 00:00:00 2001 From: Azhwani <13301425+azhwani@users.noreply.github.com> Date: Mon, 1 Apr 2024 15:54:08 +0200 Subject: [PATCH 51/92] BAEL-7499: Check if an element is present in a Set in Java (#16065) --- .../CheckIfPresentInSetUnitTest.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java new file mode 100644 index 0000000000..9d3c9a5c0d --- /dev/null +++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/checkifpresentinset/CheckIfPresentInSetUnitTest.java @@ -0,0 +1,71 @@ +package com.baeldung.checkifpresentinset; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.SetUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class CheckIfPresentInSetUnitTest { + + private static final Set CITIES = new HashSet<>(); + + @BeforeAll + static void setup() { + CITIES.add("Paris"); + CITIES.add("London"); + CITIES.add("Tokyo"); + CITIES.add("Tamassint"); + CITIES.add("New york"); + } + + @Test + void givenASet_whenUsingStreamAnyMatchMethod_thenCheck() { + boolean isPresent = CITIES.stream() + .anyMatch(city -> city.equals("London")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingStreamFilterMethod_thenCheck() { + long resultCount = CITIES.stream() + .filter(city -> city.equals("Tamassint")) + .count(); + + assertThat(resultCount).isPositive(); + } + + @Test + void givenASet_whenUsingContainsMethod_thenCheck() { + assertThat(CITIES.contains("London")).isTrue(); + assertThat(CITIES.contains("Madrid")).isFalse(); + } + + @Test + void givenASet_whenUsingCollectionsDisjointMethod_thenCheck() { + boolean isPresent = !Collections.disjoint(CITIES, Collections.singleton("Paris")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingCollectionUtilsContainsAnyMethod_thenCheck() { + boolean isPresent = CollectionUtils.containsAny(CITIES, Collections.singleton("Paris")); + + assertThat(isPresent).isTrue(); + } + + @Test + void givenASet_whenUsingSetUtilsIntersectionMethod_thenCheck() { + Set result = SetUtils.intersection(CITIES, Collections.singleton("Tamassint")); + + assertThat(result).isNotEmpty(); + } + +} From 5360ae1a35d91fa6052e4e87fe4e30eb62cfa5f4 Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:53:21 +0300 Subject: [PATCH 52/92] [JAVA-32841] (#16268) --- .../{ => config}/PersistenceProductConfiguration.java | 2 +- .../paginationsorting/ProductRepositoryIntegrationTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/{ => config}/PersistenceProductConfiguration.java (98%) diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PersistenceProductConfiguration.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java similarity index 98% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PersistenceProductConfiguration.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java index a9702a3f54..77ca127d33 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PersistenceProductConfiguration.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java @@ -1,4 +1,4 @@ -package com.baeldung.jpa.paginationsorting; +package com.baeldung.jpa.paginationsorting.config; import java.util.HashMap; diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java index 861633242d..9cf65fa949 100644 --- a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java @@ -1,9 +1,9 @@ package com.baeldung.jpa.paginationsorting; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; From dad6f36a975f7143d65d9de31d0d857c5b8b30ad Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:08:09 +0300 Subject: [PATCH 53/92] [JAVA-32836] (#16267) --- .../main/java/com/baeldung/jpa/query/{ => model}/User.java | 6 ++---- .../baeldung/jpa/query/{ => repository}/UserRepository.java | 4 +++- .../jpa/query/{ => repository}/UserRepositoryCustom.java | 4 +++- .../query/{ => repository}/UserRepositoryCustomImpl.java | 4 +++- .../jpa/query/UserQueryRepositoryIntegrationTest.java | 3 +++ 5 files changed, 14 insertions(+), 7 deletions(-) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/{ => model}/User.java (92%) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/{ => repository}/UserRepository.java (97%) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/{ => repository}/UserRepositoryCustom.java (77%) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/{ => repository}/UserRepositoryCustomImpl.java (95%) diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java similarity index 92% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/User.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java index 68b66d0801..941d045f15 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/User.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/model/User.java @@ -1,4 +1,4 @@ -package com.baeldung.jpa.query; +package com.baeldung.jpa.query.model; import java.time.LocalDate; import java.util.Objects; @@ -106,9 +106,7 @@ public class User { @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [name=").append(name).append(", id=").append(id).append("]"); - return builder.toString(); + return "User [name=" + name + ", id=" + id + "]"; } @Override diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java similarity index 97% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java index c70552e029..45739aadd4 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.jpa.query; +package com.baeldung.jpa.query.repository; import java.util.Collection; import java.util.List; @@ -12,6 +12,8 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import com.baeldung.jpa.query.model.User; + @Repository public interface UserRepository extends JpaRepository, UserRepositoryCustom { @Query("SELECT u FROM User u WHERE u.status = 1") diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java similarity index 77% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustom.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java index 22fbdab7f5..e9f906fedf 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustom.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustom.java @@ -1,10 +1,12 @@ -package com.baeldung.jpa.query; +package com.baeldung.jpa.query.repository; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.function.Predicate; +import com.baeldung.jpa.query.model.User; + public interface UserRepositoryCustom { List findUserByEmails(Set emails); diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java similarity index 95% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustomImpl.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java index 4f7d8064b9..f1c85e95e2 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/UserRepositoryCustomImpl.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/query/repository/UserRepositoryCustomImpl.java @@ -1,4 +1,4 @@ -package com.baeldung.jpa.query; +package com.baeldung.jpa.query.repository; import java.util.ArrayList; import java.util.Collection; @@ -7,6 +7,8 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.baeldung.jpa.query.model.User; + import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.criteria.CriteriaBuilder; diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java index 2c85b3b1b3..a663408a6b 100644 --- a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/query/UserQueryRepositoryIntegrationTest.java @@ -17,6 +17,9 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.JpaSort; import org.springframework.data.mapping.PropertyReferenceException; +import com.baeldung.jpa.query.model.User; +import com.baeldung.jpa.query.repository.UserRepository; + @DataJpaTest(properties = "spring.sql.init.data-locations=classpath:insert_users.sql", showSql = false) @AutoConfigurationPackage(basePackages = "com.baeldung.jpa.query") class UserQueryRepositoryIntegrationTest { From d2bcc42f673f4e1fabfe9470e87d11058ef9ad1e Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:18:07 +0300 Subject: [PATCH 54/92] [JAVA-32839] (#16266) --- .../java/com/baeldung/jpa/modifying/ModifyingApplication.java | 4 ++-- .../java/com/baeldung/jpa/modifying/model/Possession.java | 4 +--- .../src/main/java/com/baeldung/jpa/modifying/model/User.java | 4 +--- .../jpa/modifying/{dao => repository}/UserRepository.java | 2 +- .../jpa/modifying/UserRepositoryCommonIntegrationTest.java | 2 +- 5 files changed, 6 insertions(+), 10 deletions(-) rename persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/{dao => repository}/UserRepository.java (96%) diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java index 8744220a0e..af7fa9a9f1 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/ModifyingApplication.java @@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication -@EnableJpaRepositories("com.baeldung.jpa.modifying") -@EntityScan("com.baeldung.jpa.modifying") +@EnableJpaRepositories("com.baeldung.jpa.modifying.repository") +@EntityScan("com.baeldung.jpa.modifying.model") public class ModifyingApplication { public static void main(String[] args) { diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java index bc1077a3bf..b7e6051810 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/Possession.java @@ -78,9 +78,7 @@ public class Possession { @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); - return builder.toString(); + return "Possession [id=" + id + ", name=" + name + "]"; } } diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java index 651e94fef0..846d2532e5 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/model/User.java @@ -96,9 +96,7 @@ public class User { @Override public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [name=").append(name).append(", id=").append(id).append("]"); - return builder.toString(); + return "User [name=" + name + ", id=" + id + "]"; } @Override diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/dao/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java similarity index 96% rename from persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/dao/UserRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java index 34a88ae2da..3c3f9dc1b3 100644 --- a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/dao/UserRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/modifying/repository/UserRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.jpa.modifying.dao; +package com.baeldung.jpa.modifying.repository; import java.time.LocalDate; import java.util.List; diff --git a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java index fd34d0116f..872f1be985 100644 --- a/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/modifying/UserRepositoryCommonIntegrationTest.java @@ -19,7 +19,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.transaction.annotation.Transactional; -import com.baeldung.jpa.modifying.dao.UserRepository; +import com.baeldung.jpa.modifying.repository.UserRepository; import com.baeldung.jpa.modifying.model.User; import jakarta.persistence.EntityManager; From 485cab4c995b7b15eee011d6d345563404c207ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan=20Cardo=C5=9F?= <106325528+sodrac@users.noreply.github.com> Date: Tue, 2 Apr 2024 02:38:06 +0300 Subject: [PATCH 55/92] BAEL-7713 - add example merging async services response (#16280) * BAEL-7713 - add example merging async services response * BAEL-7713 update test class naming convention --- .../java/com/baeldung/async/AsyncService.java | 23 +++++++++++ .../com/baeldung/async/FirstAsyncService.java | 20 ++++++++++ .../baeldung/async/SecondAsyncService.java | 20 ++++++++++ .../baeldung/async/AsyncServiceUnitTest.java | 40 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 spring-scheduling/src/main/java/com/baeldung/async/AsyncService.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/async/FirstAsyncService.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/async/SecondAsyncService.java create mode 100644 spring-scheduling/src/test/java/com/baeldung/async/AsyncServiceUnitTest.java diff --git a/spring-scheduling/src/main/java/com/baeldung/async/AsyncService.java b/spring-scheduling/src/main/java/com/baeldung/async/AsyncService.java new file mode 100644 index 0000000000..f55fd57f53 --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/async/AsyncService.java @@ -0,0 +1,23 @@ +package com.baeldung.async; + +import java.util.concurrent.CompletableFuture; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AsyncService { + + @Autowired + private FirstAsyncService fisrtService; + @Autowired + private SecondAsyncService secondService; + + public CompletableFuture asyncMergeServicesResponse() throws InterruptedException { + CompletableFuture fisrtServiceResponse = fisrtService.asyncGetData(); + CompletableFuture secondServiceResponse = secondService.asyncGetData(); + + // Merge responses from FirstAsyncService and SecondAsyncService + return fisrtServiceResponse.thenCompose(fisrtServiceValue -> secondServiceResponse.thenApply(secondServiceValue -> fisrtServiceValue + secondServiceValue)); + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/async/FirstAsyncService.java b/spring-scheduling/src/main/java/com/baeldung/async/FirstAsyncService.java new file mode 100644 index 0000000000..fdcb236c88 --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/async/FirstAsyncService.java @@ -0,0 +1,20 @@ +package com.baeldung.async; + +import java.util.concurrent.CompletableFuture; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; +import org.springframework.stereotype.Service; + +@Service +public class FirstAsyncService { + + @Async + public CompletableFuture asyncGetData() throws InterruptedException { + System.out.println("Execute method asynchronously " + Thread.currentThread() + .getName()); + Thread.sleep(4000); + return new AsyncResult<>(super.getClass().getSimpleName() + " response !!! ").completable(); + } + +} diff --git a/spring-scheduling/src/main/java/com/baeldung/async/SecondAsyncService.java b/spring-scheduling/src/main/java/com/baeldung/async/SecondAsyncService.java new file mode 100644 index 0000000000..f5657a6e9e --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/async/SecondAsyncService.java @@ -0,0 +1,20 @@ +package com.baeldung.async; + +import java.util.concurrent.CompletableFuture; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; +import org.springframework.stereotype.Service; + +@Service +public class SecondAsyncService { + + @Async + public CompletableFuture asyncGetData() throws InterruptedException { + System.out.println("Execute method asynchronously " + Thread.currentThread() + .getName()); + Thread.sleep(4000); + return new AsyncResult<>(super.getClass().getSimpleName() + " response !!! ").completable(); + } + +} diff --git a/spring-scheduling/src/test/java/com/baeldung/async/AsyncServiceUnitTest.java b/spring-scheduling/src/test/java/com/baeldung/async/AsyncServiceUnitTest.java new file mode 100644 index 0000000000..b06544e77d --- /dev/null +++ b/spring-scheduling/src/test/java/com/baeldung/async/AsyncServiceUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.async; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.async.config.SpringAsyncConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SpringAsyncConfig.class }, loader = AnnotationConfigContextLoader.class) +public class AsyncServiceUnitTest { + + @Autowired + private AsyncService asyncServiceExample; + + // tests + + @Test + public void testAsyncAnnotationForMergedServicesResponse() throws InterruptedException, ExecutionException { + System.out.println("Invoking an asynchronous method. " + Thread.currentThread() + .getName()); + CompletableFuture completableFuture = asyncServiceExample.asyncMergeServicesResponse(); + + while (true) { + if (completableFuture.isDone()) { + System.out.println("Result from asynchronous process - " + completableFuture.get()); + break; + } + System.out.println("Continue doing something else. "); + Thread.sleep(1000); + } + } + +} From 31552ca7a59ff4f847f941ea0cfd819c0d45f77f Mon Sep 17 00:00:00 2001 From: Maiklins Date: Tue, 2 Apr 2024 21:45:33 +0200 Subject: [PATCH 56/92] Update README.md --- apache-libraries-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apache-libraries-2/README.md b/apache-libraries-2/README.md index c80677a4bc..662bdb2bcb 100644 --- a/apache-libraries-2/README.md +++ b/apache-libraries-2/README.md @@ -1,3 +1,4 @@ ## Relevant Articles - [Understanding XSLT Processing in Java](https://www.baeldung.com/java-extensible-stylesheet-language-transformations) - [Add Camel Route at Runtime in Java](https://www.baeldung.com/java-camel-dynamic-route) +- [Logging in Apache Camel](https://www.baeldung.com/java-apache-camel-logging) From 6719beae8697c55a269233b47dfe391864c92b34 Mon Sep 17 00:00:00 2001 From: Sachin Raverkar Date: Wed, 3 Apr 2024 06:44:20 +0530 Subject: [PATCH 57/92] [SR] Map enum with mapstruct (#16163) * Added enums for week day, its mapper and test. * Added enums, mapping and tests for case transformation. * Changed test names to follow BDD style. * Renamed test class. * Removed enum, mapper and test for weekdays. Added same for traffic signal. * Moved the source code and tests under its own package. * Added link to article. * Fixed readme * Fixed readme --------- Co-authored-by: sraverkar.encora --- .../enums/mapper/TrafficSignalMapper.java | 208 +++++++++++++++ .../mapstruct/enums/model/RoadSign.java | 19 ++ .../enums/model/SimpleTrafficSignal.java | 15 ++ .../mapstruct/enums/model/TrafficSignal.java | 19 ++ .../enums/model/TrafficSignalLowercase.java | 19 ++ .../enums/model/TrafficSignalNumber.java | 26 ++ .../enums/model/TrafficSignalPrefixed.java | 19 ++ .../enums/model/TrafficSignalSuffixed.java | 19 ++ .../enums/model/TrafficSignalUnderscore.java | 19 ++ .../enums/model/TrafficSignalUppercase.java | 19 ++ .../enums/TrafficSignalMapperUnitTest.java | 249 ++++++++++++++++++ 11 files changed, 631 insertions(+) create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java create mode 100644 mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java create mode 100644 mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java new file mode 100644 index 0000000000..f7bc88d95f --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/mapper/TrafficSignalMapper.java @@ -0,0 +1,208 @@ +package com.baeldung.mapstruct.enums.mapper; + +import com.baeldung.mapstruct.enums.model.*; +import org.mapstruct.*; +import org.mapstruct.factory.Mappers; + +/** + * The Traffic signal mapper. + */ +@Mapper +public interface TrafficSignalMapper { + + /** + * The constant INSTANCE. + */ + TrafficSignalMapper INSTANCE = Mappers.getMapper(TrafficSignalMapper.class); + + /** + * Convert traffic signal to integer. + * + * @param source the source + * @return the integer + */ + default Integer convertTrafficSignalToInteger(TrafficSignal source) { + Integer result = null; + switch (source) { + case Off: + result = 0; + break; + case Stop: + result = 1; + break; + case Go: + result = 2; + break; + } + return result; + } + + /** + * Maps road sign to traffic signal. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Move") + @ValueMapping(target = "Stop", source = "Halt") + TrafficSignal toTrafficSignal(RoadSign source); + + /** + * Maps string to traffic signal. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Move") + @ValueMapping(target = "Stop", source = "Halt") + TrafficSignal stringToTrafficSignal(String source); + + + /** + * Maps a traffic signal to string. + * + * @param source the source + * @return the traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "Go", source = "Go") + @ValueMapping(target = "Stop", source = "Stop") + String trafficSignalToString(TrafficSignal source); + + /** + * Maps a traffic signal to number. + * + * @param source the source + * @return the traffic signal number + */ + @Mapping(target = "number", source = ".") + TrafficSignalNumber trafficSignalToTrafficSignalNumber(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "Off", source = "Off") + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = "Stop") + SimpleTrafficSignal toSimpleTrafficSignal(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = MappingConstants.ANY_REMAINING) + SimpleTrafficSignal toSimpleTrafficSignalWithRemaining(TrafficSignal source); + + /** + * Maps traffic signal to simple traffic signal. + * + * @param source the source + * @return the simple traffic signal + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = "Off", source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithUnmapped(TrafficSignal source); + + /** + * Maps traffic signal with null handling. + * + * @param source the source + * @return the work day + */ + @ValueMapping(target = "Off", source = MappingConstants.NULL) + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = MappingConstants.NULL, source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithNullHandling(TrafficSignal source); + + /** + * Maps simple traffic signal to traffic signal with exception handling. + * + * @param source the source + * @return the work day + * @throws IllegalArgumentException if {@code source} is {@code Sat} or {@code Sun}. + */ + @ValueMapping(target = "On", source = "Go") + @ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.NULL) + @ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.ANY_UNMAPPED) + SimpleTrafficSignal toSimpleTrafficSignalWithExceptionHandling(TrafficSignal source); + + /** + * Apply suffix. + * + * @param source the source + * @return traffic signal suffixed + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION, configuration = "_Value") + TrafficSignalSuffixed applySuffix(TrafficSignal source); + + /** + * Apply prefix. + * + * @param source the source + * @return the traffic signal prefixed + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "Value_") + TrafficSignalPrefixed applyPrefix(TrafficSignal source); + + /** + * Strip suffix. + * + * @param source the source + * @return the traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION, configuration = "_Value") + TrafficSignal stripSuffix(TrafficSignalSuffixed source); + + /** + * Strip prefix. + * + * @param source the source + * @return the traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION, configuration = "Value_") + TrafficSignal stripPrefix(TrafficSignalPrefixed source); + + /** + * Apply lowercase to traffic signal. + * + * @param source the source + * @return the traffic signal lowercase + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "lower") + TrafficSignalLowercase applyLowercase(TrafficSignal source); + + /** + * Apply uppercase to traffic signal. + * + * @param source the source + * @return the traffic signal uppercase + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "upper") + TrafficSignalUppercase applyUppercase(TrafficSignal source); + + /** + * Underscore to string in capital case. + * + * @param source the source + * @return the string + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital") + String underscoreToCapital(TrafficSignalUnderscore source); + + /** + * Lowercase to capital traffic signal. + * + * @param source the source + * @return traffic signal + */ + @EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital") + TrafficSignal lowercaseToCapital(TrafficSignalLowercase source); +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java new file mode 100644 index 0000000000..1b846f98af --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/RoadSign.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum road signal. + */ +public enum RoadSign { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + Halt, + /** + * Go signal. + */ + Move +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java new file mode 100644 index 0000000000..fe58b42112 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/SimpleTrafficSignal.java @@ -0,0 +1,15 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum two-state Traffic Signal. + */ +public enum SimpleTrafficSignal { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + On +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java new file mode 100644 index 0000000000..c3691435b5 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignal.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal. + */ +public enum TrafficSignal { + /** + * Off signal. + */ + Off, + /** + * Stop signal. + */ + Stop, + /** + * Go signal. + */ + Go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java new file mode 100644 index 0000000000..f603d2f2e3 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalLowercase.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with lowercase. + */ +public enum TrafficSignalLowercase { + /** + * Off signal. + */ + off, + /** + * Stop signal. + */ + stop, + /** + * Go signal. + */ + go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java new file mode 100644 index 0000000000..8695babb39 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalNumber.java @@ -0,0 +1,26 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The traffic signal number. + */ +public class TrafficSignalNumber { + private Integer number; + + /** + * Gets number. + * + * @return the number + */ + public Integer getNumber() { + return number; + } + + /** + * Sets number. + * + * @param number the number + */ + public void setNumber(Integer number) { + this.number = number; + } +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java new file mode 100644 index 0000000000..9af4fa8ae6 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalPrefixed.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with prefix. + */ +public enum TrafficSignalPrefixed { + /** + * Off signal. + */ + Value_Off, + /** + * Stop signal. + */ + Value_Stop, + /** + * Go signal. + */ + Value_Go +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java new file mode 100644 index 0000000000..1de6c0ee14 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalSuffixed.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with suffix. + */ +public enum TrafficSignalSuffixed { + /** + * Off signal. + */ + Off_Value, + /** + * Stop signal. + */ + Stop_Value, + /** + * Go signal. + */ + Go_Value +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java new file mode 100644 index 0000000000..610df46587 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUnderscore.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with uppercase. + */ +public enum TrafficSignalUnderscore { + /** + * Off signal. + */ + OFF_VALUE, + /** + * Stop signal. + */ + STOP_VALUE, + /** + * Go signal. + */ + GO_VALUE +} diff --git a/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java new file mode 100644 index 0000000000..c9fd8f435d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapstruct/enums/model/TrafficSignalUppercase.java @@ -0,0 +1,19 @@ +package com.baeldung.mapstruct.enums.model; + +/** + * The enum Traffic Signal with uppercase. + */ +public enum TrafficSignalUppercase { + /** + * Off signal. + */ + OFF, + /** + * Stop signal. + */ + STOP, + /** + * Go signal. + */ + GO +} diff --git a/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java new file mode 100644 index 0000000000..94d0f457aa --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapstruct/enums/TrafficSignalMapperUnitTest.java @@ -0,0 +1,249 @@ +package com.baeldung.mapstruct.enums; + +import com.baeldung.mapstruct.enums.mapper.TrafficSignalMapper; +import com.baeldung.mapstruct.enums.model.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +/** + * The traffic signal mapper test. + */ +class TrafficSignalMapperUnitTest { + + /** + * To traffic signal. + */ + @Test + void whenRoadSignIsMapped_thenGetTrafficSignal() { + RoadSign source = RoadSign.Move; + TrafficSignal target = TrafficSignalMapper.INSTANCE.toTrafficSignal(source); + assertEquals(TrafficSignal.Go, target); + } + + /** + * String to traffic signal. + */ + @Test + void whenStringIsMapped_thenGetTrafficSignal() { + String source = RoadSign.Move.name(); + TrafficSignal target = TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source); + assertEquals(TrafficSignal.Go, target); + } + + /** + * String to unmapped traffic signal. + */ + @Test + void whenStringIsUnmapped_thenGetException() { + String source = "Proceed"; + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source); + }); + assertEquals("Unexpected enum constant: " + source, exception.getMessage()); + } + + /** + * Traffic signal to string. + */ + @Test + void whenTrafficSignalIsMapped_thenGetString() { + TrafficSignal source = TrafficSignal.Go; + String targetTrafficSignalStr = TrafficSignalMapper.INSTANCE.trafficSignalToString(source); + assertEquals("Go", targetTrafficSignalStr); + } + + /** + * Traffic signal to int. + * + * @param source the traffic signal + * @param expected the expected traffic signal number + */ + @ParameterizedTest + @CsvSource({"Off,0", "Stop,1"}) + void whenTrafficSignalIsMapped_thenGetInt(TrafficSignal source, int expected) { + Integer targetTrafficSignalInt = TrafficSignalMapper.INSTANCE.convertTrafficSignalToInteger(source); + TrafficSignalNumber targetTrafficSignalNumber = TrafficSignalMapper.INSTANCE.trafficSignalToTrafficSignalNumber(source); + assertEquals(expected, targetTrafficSignalInt.intValue()); + assertEquals(expected, targetTrafficSignalNumber.getNumber().intValue()); + } + + /** + * Traffic signal to simple traffic signal. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMapped_thenGetSimpleTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignal(source); + assertEquals(expected, target); + } + + /** + * Traffic signal to working day. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMappedWithRemaining_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithRemaining(source); + assertEquals(expected, targetTrafficSignal); + } + + /** + * Traffic signal to working day. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({"Off,Off", "Go,On", "Stop,Off"}) + void whenTrafficSignalIsMappedWithUnmapped_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithUnmapped(source); + assertEquals(expected, target); + } + + /** + * Traffic signal to simple traffic signal with null handling. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({",Off", "Go,On", "Stop,"}) + void whenTrafficSignalIsMappedWithNull_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithNullHandling(source); + assertEquals(expected, targetTrafficSignal); + } + + /** + * Traffic signal to traffic signal with exception handling. + * + * @param source the traffic signal + * @param expected the expected traffic signal + */ + @ParameterizedTest + @CsvSource({",", "Go,On", "Stop,"}) + void whenTrafficSignalIsMappedWithException_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) { + if (source == TrafficSignal.Go) { + SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source); + assertEquals(expected, targetTrafficSignal); + } else { + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source); + }); + assertEquals("Unexpected enum constant: " + source, exception.getMessage()); + } + } + + /** + * Apply suffix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,Off_Value", "Go,Go_Value"}) + void whenTrafficSignalIsMappedWithSuffix_thenGetTrafficSignalSuffixed(TrafficSignal source, TrafficSignalSuffixed expected) { + TrafficSignalSuffixed result = TrafficSignalMapper.INSTANCE.applySuffix(source); + assertEquals(expected, result); + } + + /** + * Apply prefix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,Value_Off", "Go,Value_Go"}) + void whenTrafficSignalIsMappedWithPrefix_thenGetTrafficSignalPrefixed(TrafficSignal source, TrafficSignalPrefixed expected) { + TrafficSignalPrefixed result = TrafficSignalMapper.INSTANCE.applyPrefix(source); + assertEquals(expected, result); + } + + /** + * Strip suffix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off_Value,Off", "Go_Value,Go"}) + void whenTrafficSignalSuffixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalSuffixed source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.stripSuffix(source); + assertEquals(expected, result); + } + + /** + * Strip prefix. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Value_Off,Off", "Value_Stop,Stop"}) + void whenTrafficSignalPrefixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalPrefixed source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.stripPrefix(source); + assertEquals(expected, result); + } + + /** + * Apply lowercase. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,off", "Go,go"}) + void whenTrafficSignalMappedWithLower_thenGetTrafficSignalLowercase(TrafficSignal source, TrafficSignalLowercase expected) { + TrafficSignalLowercase result = TrafficSignalMapper.INSTANCE.applyLowercase(source); + assertEquals(expected, result); + } + + /** + * Apply uppercase. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"Off,OFF", "Go,GO"}) + void whenTrafficSignalMappedWithUpper_thenGetTrafficSignalUppercase(TrafficSignal source, TrafficSignalUppercase expected) { + TrafficSignalUppercase result = TrafficSignalMapper.INSTANCE.applyUppercase(source); + assertEquals(expected, result); + } + + /** + * Underscore to capital. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"OFF_VALUE,Off_Value", "GO_VALUE,Go_Value"}) + void whenTrafficSignalUnderscoreMappedWithCapital_thenGetStringCapital(TrafficSignalUnderscore source, String expected) { + String result = TrafficSignalMapper.INSTANCE.underscoreToCapital(source); + assertEquals(expected, result); + } + + /** + * Lowercase to capital. + * + * @param source the traffic signal + * @param expected the expected result + */ + @ParameterizedTest + @CsvSource({"off,Off", "go,Go"}) + void whenTrafficSignalLowercaseMappedWithCapital_thenGetTrafficSignal(TrafficSignalLowercase source, TrafficSignal expected) { + TrafficSignal result = TrafficSignalMapper.INSTANCE.lowercaseToCapital(source); + assertEquals(expected, result); + } +} \ No newline at end of file From 39427baf503cec7dd6c851d4863025f7f952298d Mon Sep 17 00:00:00 2001 From: Somnath Musib <7885767+musibs@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:01:54 +0300 Subject: [PATCH 58/92] Bael 7050 Java 21 New Features (#15870) * BAEL-7050 Java 21 New Features * BAEL-7050 Formatted the pom.xml file * BAEL-7050 Moved the codebase to existing core-java-21 project * Removed the old pom.xml reference * Removed the old core-java-21-new-features project * BAEL-7050 PR Review Changes * BAEL-7050 Using JUnit5 in test cases * BAEL-7050 Using JUnit5 in test cases * BAEL-7050 Removed the public modifier from JUnit class and methods --- .../baeldung/java21/PatternCaseLabels.java | 32 +++++++++++ .../com/baeldung/java21/RecordPattern.java | 36 ++++++++++++ .../com/baeldung/java21/StringTemplates.java | 9 +++ .../com/baeldung/java21/SwitchPattern.java | 56 +++++++++++++++++++ .../java21/PatternCaseLabelsUnitTest.java | 48 ++++++++++++++++ .../java21/RecordPatternUnitTest.java | 29 ++++++++++ .../java21/StringTemplateUnitTest.java | 13 +++++ .../java21/SwitchPatternUnitTest.java | 19 +++++++ 8 files changed, 242 insertions(+) create mode 100644 core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java create mode 100644 core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java create mode 100644 core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java create mode 100644 core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java create mode 100644 core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java create mode 100644 core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java create mode 100644 core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java create mode 100644 core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java new file mode 100644 index 0000000000..7b64a382bc --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/PatternCaseLabels.java @@ -0,0 +1,32 @@ +package com.baeldung.java21; + +public class PatternCaseLabels { + + static String processInputOld(String input) { + String output; + switch (input) { + case null -> output = "Oops, null"; + case String s -> { + if ("Yes".equalsIgnoreCase(s)) { + output = "It's Yes"; + } else if ("No".equalsIgnoreCase(s)) { + output = "It's No"; + } else { + output = "Try Again"; + } + } + } + return output; + } + + static String processInputNew(String input) { + String output; + switch (input) { + case null -> output = "Oops, null"; + case String s when "Yes".equalsIgnoreCase(s) -> output = "It's Yes"; + case String s when "No".equalsIgnoreCase(s) -> output = "It's No"; + case String s -> output = "Try Again"; + } + return output; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java new file mode 100644 index 0000000000..e06539f888 --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/RecordPattern.java @@ -0,0 +1,36 @@ +package com.baeldung.java21; + +public class RecordPattern { + + record Point(int x, int y) {} + + public static int beforeRecordPattern(Object obj) { + int sum = 0; + if(obj instanceof Point p) { + int x = p.x(); + int y = p.y(); + sum = x+y; + } + return sum; + } + + public static int afterRecordPattern(Object obj) { + if(obj instanceof Point(int x, int y)) { + return x+y; + } + return 0; + } + + enum Color {RED, GREEN, BLUE} + + record ColoredPoint(Point point, Color color) {} + + record RandomPoint(ColoredPoint cp) {} + + public static Color getRamdomPointColor(RandomPoint r) { + if(r instanceof RandomPoint(ColoredPoint cp)) { + return cp.color(); + } + return null; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java new file mode 100644 index 0000000000..19dffd001b --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/StringTemplates.java @@ -0,0 +1,9 @@ +package com.baeldung.java21; + +public class StringTemplates { + + public String getStringTemplate() { + String name = "Baeldung"; + return STR."Welcome to \{name}"; + } +} diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java new file mode 100644 index 0000000000..9ef7527415 --- /dev/null +++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/java21/SwitchPattern.java @@ -0,0 +1,56 @@ +package com.baeldung.java21; + +public class SwitchPattern { + + static class Account{ + double getBalance() { + return 0; + } + } + + static class SavingsAccount extends Account { + @Override + double getBalance() { + return 100; + } + } + + static class TermAccount extends Account { + @Override + double getBalance() { + return 1000; + } + } + static class CurrentAccount extends Account { + @Override + double getBalance() { + return 10000; + } + } + + static double getBalanceWithOutSwitchPattern(Account account) { + double balance = 0; + if(account instanceof SavingsAccount sa) { + balance = sa.getBalance(); + } + else if(account instanceof TermAccount ta) { + balance = ta.getBalance(); + } + else if(account instanceof CurrentAccount ca) { + balance = ca.getBalance(); + } + return balance; + } + + static double getBalanceWithSwitchPattern(Account account) { + double result; + switch (account) { + case null -> throw new IllegalArgumentException("Oops, account is null"); + case SavingsAccount sa -> result = sa.getBalance(); + case TermAccount ta -> result = ta.getBalance(); + case CurrentAccount ca -> result = ca.getBalance(); + default -> result = account.getBalance(); + } + return result; + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java new file mode 100644 index 0000000000..07b11ff50c --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/PatternCaseLabelsUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class PatternCaseLabelsUnitTest { + + @Test + void whenProcessInputOldWayWithYes_thenReturnOutput() { + assertEquals("It's Yes", PatternCaseLabels.processInputOld("Yes")); + } + + @Test + void whenProcessInputOldWayWithNo_thenReturnOutput() { + assertEquals("It's No", PatternCaseLabels.processInputOld("No")); + } + + @Test + void whenProcessInputOldWayWithNull_thenReturnOutput() { + assertEquals("Oops, null", PatternCaseLabels.processInputOld(null)); + } + + @Test + void whenProcessInputOldWayWithInvalidOption_thenReturnOutput() { + assertEquals("Try Again", PatternCaseLabels.processInputOld("Invalid Option")); + } + + @Test + void whenProcessInputNewWayWithYes_thenReturnOutput() { + assertEquals("It's Yes", PatternCaseLabels.processInputNew("Yes")); + } + + @Test + void whenProcessInputNewWayWithNo_thenReturnOutput() { + assertEquals("It's No", PatternCaseLabels.processInputNew("No")); + } + + @Test + void whenProcessInputNewWayWithNull_thenReturnOutput() { + assertEquals("Oops, null", PatternCaseLabels.processInputNew(null)); + } + + @Test + void whenProcessInputNewWayWithInvalidOption_thenReturnOutput() { + assertEquals("Try Again", PatternCaseLabels.processInputNew("Invalid Option")); + } + +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java new file mode 100644 index 0000000000..da8f4395e0 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/RecordPatternUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +import com.baeldung.java21.RecordPattern.Color; +import com.baeldung.java21.RecordPattern.ColoredPoint; +import com.baeldung.java21.RecordPattern.Point; +import com.baeldung.java21.RecordPattern.RandomPoint; + +class RecordPatternUnitTest { + + @Test + void whenNoRecordPattern_thenReturnOutput() { + assertEquals(5, RecordPattern.beforeRecordPattern(new Point(2, 3))); + } + + @Test + void whenRecordPattern_thenReturnOutput() { + assertEquals(5, RecordPattern.afterRecordPattern(new Point(2, 3))); + } + + @Test + void whenRecordPattern_thenReturnColorOutput() { + ColoredPoint coloredPoint = new ColoredPoint(new Point(2, 3), Color.GREEN); + RandomPoint randomPoint = new RandomPoint(coloredPoint); + assertEquals(Color.GREEN, RecordPattern.getRamdomPointColor(randomPoint)); + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java new file mode 100644 index 0000000000..340e9b54d9 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/StringTemplateUnitTest.java @@ -0,0 +1,13 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class StringTemplateUnitTest { + + @Test + void whenNoSwitchPattern_thenReturnSavingsAccountBalance() { + StringTemplates stringTemplates = new StringTemplates(); + assertEquals("Welcome to Baeldung", stringTemplates.getStringTemplate()); + } +} diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java new file mode 100644 index 0000000000..7429b303e9 --- /dev/null +++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/java21/SwitchPatternUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.java21; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +class SwitchPatternUnitTest { + + @Test + void whenNoSwitchPattern_thenReturnSavingsAccountBalance() { + SwitchPattern.SavingsAccount savingsAccount = new SwitchPattern.SavingsAccount(); + assertEquals(100, SwitchPattern.getBalanceWithOutSwitchPattern(savingsAccount), 0); + } + + @Test + void whenSwitchPattern_thenReturnSavingsAccountBalance() { + SwitchPattern.SavingsAccount savingsAccount = new SwitchPattern.SavingsAccount(); + assertEquals(100, SwitchPattern.getBalanceWithSwitchPattern(savingsAccount), 0); + } +} From 0eaafc735e81bf6d3cfcf2b05aacdde3c2bf1123 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:45:43 +0800 Subject: [PATCH 59/92] Update README.md --- persistence-modules/hibernate-queries/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate-queries/README.md b/persistence-modules/hibernate-queries/README.md index 9e6c52d6dc..60a84de779 100644 --- a/persistence-modules/hibernate-queries/README.md +++ b/persistence-modules/hibernate-queries/README.md @@ -13,3 +13,4 @@ This module contains articles about use of Queries in Hibernate. - [Distinct Queries in HQL](https://www.baeldung.com/java-hql-distinct) - [JPA and Hibernate – Criteria vs. JPQL vs. HQL Query](https://www.baeldung.com/jpql-hql-criteria-query) - [Database Keywords as Columns in Hibernate Entities](https://www.baeldung.com/java-hibernate-db-keywords-as-columns) +- [Get List of Entity From Database in Hibernate](https://www.baeldung.com/java-hibernate-fetch-entity-list) From 16d52de59d2c9862f4ca87e6951149d776e72157 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:47:45 +0800 Subject: [PATCH 60/92] Update README.md --- core-java-modules/core-java-io-apis/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-io-apis/README.md b/core-java-modules/core-java-io-apis/README.md index faf7067f74..ee8547f0c5 100644 --- a/core-java-modules/core-java-io-apis/README.md +++ b/core-java-modules/core-java-io-apis/README.md @@ -13,3 +13,4 @@ This module contains articles about core Java input/output(IO) APIs. - [Difference Between FileReader and BufferedReader in Java](https://www.baeldung.com/java-filereader-vs-bufferedreader) - [Read Multiple Inputs on the Same Line in Java](https://www.baeldung.com/java-read-multiple-inputs-same-line) - [Write Console Output to Text File in Java](https://www.baeldung.com/java-write-console-output-file) +- [Java InputStream vs. InputStreamReader](https://www.baeldung.com/java-inputstream-vs-inputstreamreader) From a0baf74cb20040a9e9a17a5563dcdf53b3e9c660 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:52:52 +0800 Subject: [PATCH 61/92] Update README.md --- spring-di-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-di-4/README.md b/spring-di-4/README.md index 7301339d33..69b769d07e 100644 --- a/spring-di-4/README.md +++ b/spring-di-4/README.md @@ -9,4 +9,5 @@ This module contains articles about dependency injection with Spring - [Why Is Field Injection Not Recommended?](https://www.baeldung.com/java-spring-field-injection-cons) - [Setting a Spring Bean to Null](https://www.baeldung.com/spring-setting-bean-null) - [Dynamically Register Spring Beans Based on Properties](https://www.baeldung.com/spring-beans-dynamic-registration-properties) +- [Create Spring Prototype Scope Bean with Runtime Arguments](https://www.baeldung.com/spring-prototype-bean-runtime-arguments) - More articles: [[<-- prev]](../spring-di-3) From e8f8b6d7fe2d5d9f1123cd33e35ca28125f36840 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:55:47 +0800 Subject: [PATCH 62/92] Update README.md --- microservices-modules/saga-pattern/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/microservices-modules/saga-pattern/README.md b/microservices-modules/saga-pattern/README.md index 853cce4c5e..95a090fe72 100644 --- a/microservices-modules/saga-pattern/README.md +++ b/microservices-modules/saga-pattern/README.md @@ -10,4 +10,7 @@ This is an example project showing how to build event driven applications using ```shell docker run --init -p 8080:8080 -p 1234:5000 conductoross/conductor-standalone:3.15.0 -``` \ No newline at end of file +``` + +### Relevant Articles: +- [Saga Pattern in Microservices Architecture](https://www.baeldung.com/orkes-conductor-saga-pattern-spring-boot) From 19e7692e91eafdf55a1469ca1a6ba4564ed4bc00 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:58:02 +0800 Subject: [PATCH 63/92] Update README.md --- testing-modules/mockito-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md index 263c890450..4d93bbcb23 100644 --- a/testing-modules/mockito-2/README.md +++ b/testing-modules/mockito-2/README.md @@ -11,3 +11,4 @@ This module contains articles about Mockito - [Overview of Mockito MockedConstruction](https://www.baeldung.com/java-mockito-mockedconstruction) - [Verify That Lambda Expression Was Called Using Mockito](https://www.baeldung.com/java-mockito-verify-lambda-expression) - [Injecting @Mock and @Captor in JUnit 5 Method Parameters](https://www.baeldung.com/junit-5-mock-captor-method-parameter-injection) +- [Fix Ambiguous Method Call Error in Mockito](https://www.baeldung.com/mockito-fix-ambiguous-method-call-error) From f85d5f537b2a0da03d7ac80db7cfc7770f3a5cb9 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:59:45 +0800 Subject: [PATCH 64/92] Update README.md --- json-modules/json-conversion/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/json-modules/json-conversion/README.md b/json-modules/json-conversion/README.md index f2f6ec7d28..5878f4e194 100644 --- a/json-modules/json-conversion/README.md +++ b/json-modules/json-conversion/README.md @@ -9,3 +9,4 @@ This module contains articles about JSON Conversions - [Preventing Gson from Expressing Integers as Floats](https://www.baeldung.com/java-gson-prevent-expressing-integers-as-floats) - [Simplified Array Operations on JsonNode Without Typecasting in Jackson](https://www.baeldung.com/java-jsonnode-persistence-simplified-array-operations) - [How to Convert Excel to JSON in Java](https://www.baeldung.com/java-excel-json-conversion) +- [Include null Value in JSON Serialization](https://www.baeldung.com/java-json-null-serialization) From 1c4caceec0bf086e00a265530d930de4f490d01c Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:01:26 +0800 Subject: [PATCH 65/92] Update README.md --- persistence-modules/hibernate-annotations/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate-annotations/README.md b/persistence-modules/hibernate-annotations/README.md index 663c39ea33..446dde9ece 100644 --- a/persistence-modules/hibernate-annotations/README.md +++ b/persistence-modules/hibernate-annotations/README.md @@ -13,3 +13,4 @@ This module contains articles about Annotations used in Hibernate. - [Hibernate @CreationTimestamp and @UpdateTimestamp](https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp) - [Difference Between @JoinColumn and @PrimaryKeyJoinColumn in JPA](https://www.baeldung.com/java-jpa-join-vs-primarykeyjoin) - [A Guide to the @SoftDelete Annotation in Hibernate](https://www.baeldung.com/java-hibernate-softdelete-annotation) +- [@Subselect Annotation in Hibernate](https://www.baeldung.com/hibernate-subselect) From f0e8cef1fc331aece3d1f9b30129b2da47b34ee0 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:03:08 +0800 Subject: [PATCH 66/92] Update README.md --- core-java-modules/core-java-collections-maps-8/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-collections-maps-8/README.md b/core-java-modules/core-java-collections-maps-8/README.md index 0dd8c780d6..f3dcc6b8bb 100644 --- a/core-java-modules/core-java-collections-maps-8/README.md +++ b/core-java-modules/core-java-collections-maps-8/README.md @@ -1 +1,2 @@ -## Relevant Articles: \ No newline at end of file +### Relevant Articles: +- [Find Map Keys with Duplicate Values in Java](https://www.baeldung.com/java-map-find-keys-repeated-values) From 7b3faa18ad0cc4e399d3e50bffd57adc93b26500 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:04:46 +0800 Subject: [PATCH 67/92] Update README.md --- algorithms-modules/algorithms-miscellaneous-8/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms-modules/algorithms-miscellaneous-8/README.md b/algorithms-modules/algorithms-miscellaneous-8/README.md index c3d689fa13..e2c5047136 100644 --- a/algorithms-modules/algorithms-miscellaneous-8/README.md +++ b/algorithms-modules/algorithms-miscellaneous-8/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Vigenère Cipher in Java](https://www.baeldung.com/java-vigenere-cipher) +- [Merge Overlapping Intervals in a Java Collection](https://www.baeldung.com/java-collection-merge-overlapping-intervals) From 2a4441ceb4d6164355185e2aaf44f29c60a62e86 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:05:54 +0800 Subject: [PATCH 68/92] Update README.md --- testing-modules/selenium-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/selenium-2/README.md b/testing-modules/selenium-2/README.md index a1d180814d..2ab7037b88 100644 --- a/testing-modules/selenium-2/README.md +++ b/testing-modules/selenium-2/README.md @@ -3,6 +3,7 @@ - [Fixing Selenium WebDriver Executable Path Error](https://www.baeldung.com/java-selenium-webdriver-path-error) - [Implicit Wait vs Explicit Wait in Selenium Webdriver](https://www.baeldung.com/selenium-implicit-explicit-wait) - [Switching Between Frames Using Selenium WebDriver in Java](https://www.baeldung.com/java-selenium-change-frames) +- [Finding Element by Attribute in Selenium](https://www.baeldung.com/selenium-find-element-by-attribute) #### Notes: - to run the live tests for the article *Fixing Selenium WebDriver Executable Path Error*, follow the manual setup described From eb73935257341309b40e7af08cc04f519d94d9c8 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:07:54 +0800 Subject: [PATCH 69/92] Update README.md --- persistence-modules/hibernate-jpa/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/persistence-modules/hibernate-jpa/README.md b/persistence-modules/hibernate-jpa/README.md index 5599140732..feab5f4d9a 100644 --- a/persistence-modules/hibernate-jpa/README.md +++ b/persistence-modules/hibernate-jpa/README.md @@ -13,4 +13,5 @@ This module contains articles specific to use of Hibernate as a JPA implementati - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) - [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) -- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) \ No newline at end of file +- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) +- [The @Struct Annotation Type in Hibernate – Structured User-Defined Types](https://www.baeldung.com/java-hibernate-struct-annotation) From 278e6cebdcb15dc25b375bbbf554219eab515d5b Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:08:58 +0800 Subject: [PATCH 70/92] Update README.md --- core-java-modules/core-java-string-operations-8/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-operations-8/README.md b/core-java-modules/core-java-string-operations-8/README.md index 2515e07be4..018fcdc987 100644 --- a/core-java-modules/core-java-string-operations-8/README.md +++ b/core-java-modules/core-java-string-operations-8/README.md @@ -8,3 +8,4 @@ - [Get the Initials of a Name in Java](https://www.baeldung.com/java-shorten-name-initials) - [Normalizing the EOL Character in Java](https://www.baeldung.com/java-normalize-end-of-line-character) - [Converting UTF-8 to ISO-8859-1 in Java](https://www.baeldung.com/java-utf-8-iso-8859-1-conversion) +- [Get Last n Characters From a String](https://www.baeldung.com/java-string-get-last-n-characters) From d8a03d93d991afc15d444dc02a804dbb74850ddb Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:09:56 +0800 Subject: [PATCH 71/92] Update README.md --- spring-boot-modules/spring-boot-logging-loki/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-logging-loki/README.md b/spring-boot-modules/spring-boot-logging-loki/README.md index e320af31b4..376f9d803f 100644 --- a/spring-boot-modules/spring-boot-logging-loki/README.md +++ b/spring-boot-modules/spring-boot-logging-loki/README.md @@ -1 +1,2 @@ -### Relevant Articles: \ No newline at end of file +### Relevant Articles: +- [Logging in Spring Boot With Loki](https://www.baeldung.com/spring-boot-loki-grafana-logging) From 6c33d80eca3ec643d9e1e90ddb8a06e1fd2ec718 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:10:54 +0800 Subject: [PATCH 72/92] Update README.md --- core-java-modules/core-java-collections-set-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-set-2/README.md b/core-java-modules/core-java-collections-set-2/README.md index ee41908faf..1eed623824 100644 --- a/core-java-modules/core-java-collections-set-2/README.md +++ b/core-java-modules/core-java-collections-set-2/README.md @@ -6,4 +6,5 @@ - [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set) - [Cartesian Product of Any Number of Sets in Java](https://www.baeldung.com/java-cartesian-product-sets) - [How to Get Index of an Item in Java Set](https://www.baeldung.com/java-set-element-find-index) +- [Check if an Element Is Present in a Set in Java](https://www.baeldung.com/java-set-membership) - More articles: [[<-- prev]](/core-java-modules/core-java-collections-set) From a97ddc25b78e7f7c828f4a4168949c82032b92e1 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:12:04 +0800 Subject: [PATCH 73/92] Update README.md --- core-java-modules/core-java-datetime-conversion-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-datetime-conversion-2/README.md b/core-java-modules/core-java-datetime-conversion-2/README.md index 7fe174b385..1a2d1b300b 100644 --- a/core-java-modules/core-java-datetime-conversion-2/README.md +++ b/core-java-modules/core-java-datetime-conversion-2/README.md @@ -5,3 +5,4 @@ This module contains articles about converting between Java date and time object ### Relevant Articles: - [Convert Gregorian to Hijri Date in Java](https://www.baeldung.com/java-date-gregorian-hijri-conversion) - [Convert String Date to XMLGregorianCalendar in Java](https://www.baeldung.com/java-string-date-xmlgregoriancalendar-conversion) +- [Convert TemporalAccessor to LocalDate](https://www.baeldung.com/java-temporalaccessor-localdate-conversion) From 7d46346e9f18c390777726f5033b00a90854a523 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:13:17 +0800 Subject: [PATCH 74/92] Update README.md --- core-java-modules/core-java-io-apis-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-io-apis-2/README.md b/core-java-modules/core-java-io-apis-2/README.md index 29666826a8..2b08736a11 100644 --- a/core-java-modules/core-java-io-apis-2/README.md +++ b/core-java-modules/core-java-io-apis-2/README.md @@ -11,3 +11,4 @@ This module contains articles about core Java input/output(IO) APIs. - [PrintWriter vs. FileWriter in Java](https://www.baeldung.com/java-printwriter-filewriter-difference) - [Read Input Character-by-Character in Java](https://www.baeldung.com/java-read-input-character) - [Difference Between flush() and close() in Java FileWriter](https://www.baeldung.com/java-filewriter-flush-vs-close) +- [Get a Path to a Resource in a Java JAR File](https://www.baeldung.com/java-get-path-resource-jar) From aa8016e8388118485188f0cc95c12950ffc35d96 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Thu, 4 Apr 2024 07:05:25 +0200 Subject: [PATCH 75/92] [JAVA-32852] Fix UrlCheckerIntegrationTest (#16292) --- .../java/com/baeldung/url/UrlCheckerIntegrationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java index e3100deebc..edafe242c1 100644 --- a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java +++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java @@ -11,28 +11,28 @@ public class UrlCheckerIntegrationTest { @Test public void givenValidUrl_WhenUsingHEAD_ThenReturn200() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com"); + int responseCode = tester.getResponseCodeForURLUsingHead("https://httpbin.org/status/200"); assertEquals(200, responseCode); } @Test public void givenInvalidIUrl_WhenUsingHEAD_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com/xyz"); + int responseCode = tester.getResponseCodeForURLUsingHead("https://httpbin.org/status/404"); assertEquals(404, responseCode); } @Test public void givenValidUrl_WhenUsingGET_ThenReturn200() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURL("http://www.example.com"); + int responseCode = tester.getResponseCodeForURL("https://httpbin.org/status/200"); assertEquals(200, responseCode); } @Test public void givenInvalidIUrl_WhenUsingGET_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURL("http://www.example.com/xyz"); + int responseCode = tester.getResponseCodeForURL("https://httpbin.org/status/404"); assertEquals(404, responseCode); } From d21e80d93d976a1ddeebbf337336ab9550fdef61 Mon Sep 17 00:00:00 2001 From: sam-gardner <53271849+sam-gardner@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:05:48 +0100 Subject: [PATCH 76/92] JAVA-32067 Upgrade spring thymeleaf to spring boot 3 (#16129) --- spring-web-modules/spring-thymeleaf-4/pom.xml | 4 ++-- .../thymeleaf/expression/DinoController.java | 4 ++-- .../thymeleaf/mvcdata/EmailController.java | 19 ++----------------- .../{templates-3 => templates-2}/form.html | 0 .../{templates-3 => templates-2}/index.html | 0 .../{templates-3 => templates-2}/result.html | 0 .../mvcdata/email-servlet-context.html | 14 -------------- .../mvcdata/email-session-attributes.html | 14 -------------- .../main/resources/templates/url/index.html | 3 --- .../mvcdata/EmailControllerUnitTest.java | 14 -------------- 10 files changed, 6 insertions(+), 66 deletions(-) rename spring-web-modules/spring-thymeleaf-4/src/main/resources/{templates-3 => templates-2}/form.html (100%) rename spring-web-modules/spring-thymeleaf-4/src/main/resources/{templates-3 => templates-2}/index.html (100%) rename spring-web-modules/spring-thymeleaf-4/src/main/resources/{templates-3 => templates-2}/result.html (100%) delete mode 100644 spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-servlet-context.html delete mode 100644 spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-session-attributes.html diff --git a/spring-web-modules/spring-thymeleaf-4/pom.xml b/spring-web-modules/spring-thymeleaf-4/pom.xml index 2582044c0f..1e6be32801 100644 --- a/spring-web-modules/spring-thymeleaf-4/pom.xml +++ b/spring-web-modules/spring-thymeleaf-4/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/expression/DinoController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/expression/DinoController.java index 6cbf1bae0e..ad2875106d 100644 --- a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/expression/DinoController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/expression/DinoController.java @@ -23,7 +23,7 @@ public class DinoController { model.addAttribute("dinos", dinos); System.out.println(dinos); - return "templates-3/index"; + return "index"; } @@ -32,7 +32,7 @@ public class DinoController { model.addAttribute("dinos", new Dino()); - return "templates-3/form"; + return "form"; } diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java index 1bfe3f3428..bdf303ef62 100644 --- a/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java +++ b/spring-web-modules/spring-thymeleaf-4/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java @@ -1,7 +1,7 @@ package com.baeldung.thymeleaf.mvcdata; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpSession; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -41,21 +41,6 @@ public class EmailController { return "mvcdata/email-request-parameters"; } - @GetMapping("/email/sessionattributes") - public String emailSessionAttributes(HttpSession httpSession) { - httpSession.setAttribute("emaildata", emailData); - return "mvcdata/email-session-attributes"; - } - - @GetMapping("/email/servletcontext") - public String emailServletContext() { - servletContext.setAttribute("emailsubject", emailData.getEmailSubject()); - servletContext.setAttribute("emailcontent", emailData.getEmailBody()); - servletContext.setAttribute("emailaddress", emailData.getEmailAddress1()); - servletContext.setAttribute("emaillocale", emailData.getEmailLocale()); - return "mvcdata/email-servlet-context"; - } - @GetMapping("/email/beandata") public String emailBeanData() { return "mvcdata/email-bean-data"; diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/form.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/form.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/form.html rename to spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/form.html diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/index.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/index.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/index.html rename to spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/index.html diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/result.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/result.html similarity index 100% rename from spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-3/result.html rename to spring-web-modules/spring-thymeleaf-4/src/main/resources/templates-2/result.html diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-servlet-context.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-servlet-context.html deleted file mode 100644 index b07573047e..0000000000 --- a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-servlet-context.html +++ /dev/null @@ -1,14 +0,0 @@ - - - -

Subject

-

-

Content

-

-

Email address

-

-

Language

-

- - \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-session-attributes.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-session-attributes.html deleted file mode 100644 index 9227171fc6..0000000000 --- a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/mvcdata/email-session-attributes.html +++ /dev/null @@ -1,14 +0,0 @@ - - - -

Subject

-

-

Content

-

-

Email address

-

-

Language

-

- - \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/url/index.html b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/url/index.html index a8ac95aea3..9eabfd8e42 100644 --- a/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/url/index.html +++ b/spring-web-modules/spring-thymeleaf-4/src/main/resources/templates/url/index.html @@ -10,8 +10,5 @@

-
-

-
\ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java index 5e1190e174..12742e626c 100644 --- a/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java +++ b/spring-web-modules/spring-thymeleaf-4/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java @@ -48,20 +48,6 @@ public class EmailControllerUnitTest { .andExpect(content().string(containsString("en-US"))); } - @Test - public void whenCallSessionAttributes_thenReturnEmailData() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/email/sessionattributes")) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Good morning !"))); - } - - @Test - public void whenCallServletContext_thenReturnEmailData() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/email/servletcontext")) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("jhon.doe@example.com"))); - } - @Test public void whenCallBeanData_thenReturnEmailData() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/email/beandata")) From 37eb20833e56c7c419c3e37db3acec19fd389d24 Mon Sep 17 00:00:00 2001 From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:00:20 +0200 Subject: [PATCH 77/92] BAEL-7765: How to fix JsonParseException: Unexpected character (code 115) when parsing unquoted JSON in Jackson (#16286) --- .../exceptions/JacksonExceptionsUnitTest.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java b/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java index 127d466436..e1517ed09b 100644 --- a/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java +++ b/jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java @@ -1,16 +1,5 @@ package com.baeldung.exceptions; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.List; - -import org.junit.Test; - import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonFactory; @@ -22,6 +11,13 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.*; public class JacksonExceptionsUnitTest { @@ -201,6 +197,16 @@ public class JacksonExceptionsUnitTest { .readValue(json); } + // JsonParseException: Unexpected character ('n' (code 110)) + @Test(expected = JsonParseException.class) + public void givenInvalidJsonString_whenDeserializing_thenException() throws JsonProcessingException, IOException { + final String json = "{\"id\":1, name:\"John\"}"; // Missing double quotes around 'name' + final ObjectMapper mapper = new ObjectMapper(); + mapper.reader() + .forType(User.class) + .readValue(json); + } + @Test public void givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect() throws JsonProcessingException, IOException { final String json = "{'id':1,'name':'John'}"; From 2f28252a7d2f0a7da9b2f0e9ded773cbcf1bd650 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Thu, 4 Apr 2024 22:09:18 +0200 Subject: [PATCH 78/92] [JAVA-31765] Upgrade gitflow-incremental-builder to version 4.5.3 (#16090) --- pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d9c7e439b8..57bc8bbfb3 100644 --- a/pom.xml +++ b/pom.xml @@ -234,7 +234,7 @@ - com.vackosar.gitflowincrementalbuilder + io.github.gitflow-incremental-builder gitflow-incremental-builder ${gitflow-incremental-builder.version} @@ -1142,6 +1142,7 @@ false false true + .*gradle-modules.* 4.13.2 @@ -1182,7 +1183,7 @@ 1.0 3.1.1 0.0.1 - 3.12.2 + 4.5.3 3.3.0 3.21.0 1.18.30 From cc90a0b8bb3631721c5b9e40395e382e47a73469 Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:24:46 +0300 Subject: [PATCH 79/92] JAVA-31057 Check if large files can be removed (#16278) * JAVA-31057 Check if large files can be removed * JAVA-31057 Remove un-needed files from spring boot telegram --------- Co-authored-by: timis1 --- .../src/main/resources/images/sampleImage.jpg | Bin 1196848 -> 163888 bytes .../spring-boot-telegram/baeldungbot | Bin 2097152 -> 0 bytes .../static/home/inline.bundle.js.map | 1 - .../resources/static/home/main.bundle.js.map | 1 - .../static/home/polyfills.bundle.js.map | 1 - .../static/home/styles.bundle.js.map | 1 - 6 files changed, 4 deletions(-) delete mode 100644 spring-boot-modules/spring-boot-telegram/baeldungbot delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/inline.bundle.js.map delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/main.bundle.js.map delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/polyfills.bundle.js.map delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/static/home/styles.bundle.js.map diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg b/algorithms-modules/algorithms-miscellaneous-7/src/main/resources/images/sampleImage.jpg index c2f035ae641a65204846264c6507a2146c4929d6..5efe04c33a295f79ebfccf1bec2033e51ea17729 100644 GIT binary patch literal 163888 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