From fe08da3851bd47425e9dba857659e3a793b074e4 Mon Sep 17 00:00:00 2001 From: samdalvai Date: Thu, 30 Jun 2022 23:28:16 +0200 Subject: [PATCH 01/39] Fix naming of parameters in documentation --- .../batch/repository/ProductRepository.java | 13 +++++++------ .../java/client/repository/KeyspaceRepository.java | 10 +++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java index 106db133d1..9df145e064 100644 --- a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/batch/repository/ProductRepository.java @@ -62,12 +62,13 @@ public class ProductRepository { executeStatement(createTable.build(), keyspace); } - + /** - * Insert two variant Product into same table using a batch query. - * - * @param Product - */ + * Insert two variant Product into same table using a batch query. + * + * @param productVariant1 + * @param productVariant2 + */ public void insertProductVariantBatch(Product productVariant1,Product productVariant2) { UUID productId = UUID.randomUUID(); BoundStatement productBoundStatement1 = this.getProductVariantInsertStatement(productVariant1,productId); @@ -83,7 +84,7 @@ public class ProductRepository { /** * Insert two same Product into related tables using a batch query. * - * @param book + * @param product */ public void insertProductBatch(Product product) { UUID productId = UUID.randomUUID(); diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java index f15558f040..943ecf8b28 100644 --- a/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java @@ -16,13 +16,13 @@ public class KeyspaceRepository { /** * Method used to create any keyspace - schema. * - * @param schemaName the name of the schema. - * @param replicatioonStrategy the replication strategy. + * @param keyspaceName the name of the keyspaceName. + * @param replicationStrategy the replication strategy. * @param numberOfReplicas the number of replicas. * */ - public void createKeyspace(String keyspaceName, String replicatioonStrategy, int numberOfReplicas) { - StringBuilder sb = new StringBuilder("CREATE KEYSPACE IF NOT EXISTS ").append(keyspaceName).append(" WITH replication = {").append("'class':'").append(replicatioonStrategy).append("','replication_factor':").append(numberOfReplicas).append("};"); + public void createKeyspace(String keyspaceName, String replicationStrategy, int numberOfReplicas) { + StringBuilder sb = new StringBuilder("CREATE KEYSPACE IF NOT EXISTS ").append(keyspaceName).append(" WITH replication = {").append("'class':'").append(replicationStrategy).append("','replication_factor':").append(numberOfReplicas).append("};"); final String query = sb.toString(); @@ -37,7 +37,7 @@ public class KeyspaceRepository { * Method used to delete the specified schema. * It results in the immediate, irreversable removal of the keyspace, including all tables and data contained in the keyspace. * - * @param schemaName the name of the keyspace to delete. + * @param keyspaceName the name of the keyspace to delete. */ public void deleteKeyspace(String keyspaceName) { StringBuilder sb = new StringBuilder("DROP KEYSPACE ").append(keyspaceName); From 48461ed6cc86333c7bd414537089b27d09cb7400 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 26 Jul 2022 18:38:10 +0530 Subject: [PATCH 02/39] JAVA-13628 Minor upgrades --- .../MockitoVerifyExamplesUnitTest.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoVerifyExamplesUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoVerifyExamplesUnitTest.java index f138256e72..c3c5758950 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoVerifyExamplesUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoVerifyExamplesUnitTest.java @@ -1,6 +1,17 @@ package com.baeldung.mockito; -import com.google.common.collect.Lists; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import java.util.List; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -8,11 +19,7 @@ import org.mockito.InOrder; import org.mockito.Mockito; import org.mockito.exceptions.verification.NoInteractionsWanted; -import java.util.List; - -import static org.hamcrest.Matchers.hasItem; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.*; +import com.google.common.collect.Lists; public class MockitoVerifyExamplesUnitTest { @@ -108,10 +115,12 @@ public class MockitoVerifyExamplesUnitTest { public final void whenVerifyingAnInteractionWithArgumentCapture_thenCorrect() { final List mockedList = mock(MyList.class); mockedList.addAll(Lists.newArrayList("someElement")); - final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(List.class); + + final ArgumentCaptor> argumentCaptor = ArgumentCaptor.forClass(List.class); verify(mockedList).addAll(argumentCaptor.capture()); - final List capturedArgument = argumentCaptor.>getValue(); - assertThat(capturedArgument, hasItem("someElement")); + + final List capturedArgument = argumentCaptor.getValue(); + assertThat(capturedArgument).contains("someElement"); } } From 9f31e46b0333dafbdab0e8d133a3ab3188ce2f97 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 26 Jul 2022 23:31:25 +0530 Subject: [PATCH 03/39] JAVA-13629 Added missing tests from Mockito ArgumentMatchers article --- .../baeldung/app/rest/FlowerController.java | 2 +- .../domain/service/FlowerService.java | 2 +- .../app/rest/FlowerControllerUnitTest.java | 80 ++++++++++++++----- .../app/rest/MessageControllerUnitTest.java | 51 +++++++----- 4 files changed, 96 insertions(+), 39 deletions(-) diff --git a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/FlowerController.java b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/FlowerController.java index b3d8888cec..10f602088c 100644 --- a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/FlowerController.java +++ b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/FlowerController.java @@ -17,7 +17,7 @@ public class FlowerController { @PostMapping("/isAFlower") public String isAFlower (@RequestBody String flower) { - return flowerService.analize(flower); + return flowerService.analyze(flower); } @PostMapping("/isABigFlower") diff --git a/testing-modules/mockito-simple/src/main/java/com/baeldung/domain/service/FlowerService.java b/testing-modules/mockito-simple/src/main/java/com/baeldung/domain/service/FlowerService.java index 3c76cb5d76..74a9308890 100644 --- a/testing-modules/mockito-simple/src/main/java/com/baeldung/domain/service/FlowerService.java +++ b/testing-modules/mockito-simple/src/main/java/com/baeldung/domain/service/FlowerService.java @@ -10,7 +10,7 @@ public class FlowerService { private List flowers = Arrays.asList("Poppy", "Ageratum", "Carnation", "Diascia", "Lantana"); - public String analize(String name) { + public String analyze(String name) { if(flowers.contains(name)) { return "flower"; } diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/FlowerControllerUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/FlowerControllerUnitTest.java index aeec57d136..df3561d646 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/FlowerControllerUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/FlowerControllerUnitTest.java @@ -1,14 +1,20 @@ package com.baeldung.app.rest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.AdditionalMatchers.or; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.exceptions.misusing.InvalidUseOfMatchersException; import org.mockito.junit.MockitoJUnitRunner; import com.baeldung.app.api.Flower; @@ -17,29 +23,67 @@ import com.baeldung.domain.service.FlowerService; @RunWith(MockitoJUnitRunner.class) public class FlowerControllerUnitTest { - @Mock - private FlowerService flowerService; + @InjectMocks + private FlowerController flowerController; - @InjectMocks - private FlowerController flowerController; + @Mock + private FlowerService flowerService; - @Test - public void isAFlower_withMockito_OK() { - when(flowerService.analize(eq("violetta"))).thenReturn("Flower"); + @Test + public void givenPoppyFlower_whenUsingDoReturn_thenCorrect() { + doReturn("Flower").when(flowerService).analyze("poppy"); - String response = flowerController.isAFlower("violetta"); + String response = flowerController.isAFlower("poppy"); + assertThat(response).isEqualTo("Flower"); + } - Assert.assertEquals("Flower", response); - } + @Test + public void givenAnyString_whenUsingArgumentMatcher_thenCorrect() { + when(flowerService.analyze(anyString())).thenReturn("Flower"); - @Test - public void isABigFlower_withMockito_OK() { - when(flowerService.isABigFlower(eq("violetta"), anyInt())).thenReturn(true); + String response = flowerController.isAFlower("violetta"); + assertThat(response).isEqualTo("Flower"); + } - Flower flower = new Flower("violetta", 15); + @Test(expected = InvalidUseOfMatchersException.class) + public void whenIncorrectMatchers_thenThrowsError() { + when(flowerService.isABigFlower("poppy", anyInt())).thenReturn(true); - Boolean response = flowerController.isABigFlower(flower); + Flower flower = new Flower("poppy", 15); - Assert.assertTrue(response); - } + Boolean response = flowerController.isABigFlower(flower); + assertThat(response).isTrue(); + } + + @Test + public void whenCorrectMatchers_thenCorrect() { + when(flowerService.isABigFlower(eq("poppy"), anyInt())).thenReturn(true); + + Flower flower = new Flower("poppy", 15); + + Boolean response = flowerController.isABigFlower(flower); + assertThat(response).isTrue(); + } + + @Test(expected = InvalidUseOfMatchersException.class) + public void whenUsingMatchersAsReturnValue_thenThrowsError() { + flowerController.isAFlower("poppy"); + + String orMatcher = or(eq("poppy"), endsWith("y")); + verify(flowerService).analyze(orMatcher); + } + + @Test + public void whenUsingMatchersAsOngoingStubbing_thenCorrect1() { + flowerController.isAFlower("poppy"); + + verify(flowerService).analyze(or(eq("poppy"), endsWith("y"))); + } + + @Test + public void whenUsingMatchersAsOngoingStubbing_thenCorrect2() { + flowerController.isAFlower("lily"); + + verify(flowerService).analyze(or(eq("poppy"), endsWith("y"))); + } } diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java index 15e91d86b5..ae368c4c34 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java @@ -1,13 +1,14 @@ package com.baeldung.app.rest; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import com.baeldung.app.api.MessageApi; @@ -18,26 +19,38 @@ import com.baeldung.domain.util.MessageMatcher; @RunWith(MockitoJUnitRunner.class) public class MessageControllerUnitTest { - @Mock - private MessageService messageService; + @Mock + private MessageService messageService; - @InjectMocks - private MessageController messageController; + @InjectMocks + private MessageController messageController; - @Test - public void createMessage_NewMessage_OK() { - MessageApi messageApi = new MessageApi(); - messageApi.setFrom("me"); - messageApi.setTo("you"); - messageApi.setText("Hello, you!"); + @Test + public void givenMsg_whenVerifyUsingAnyMatcher_thenOk() { + MessageApi messageApi = new MessageApi(); + messageApi.setFrom("me"); + messageApi.setTo("you"); + messageApi.setText("Hello, you!"); - messageController.createMessage(messageApi); + messageController.createMessage(messageApi); - Message message = new Message(); - message.setFrom("me"); - message.setTo("you"); - message.setText("Hello, you!"); + verify(messageService, times(1)).deliverMessage(any(Message.class)); + } - Mockito.verify(messageService, times(1)).deliverMessage(ArgumentMatchers.argThat(new MessageMatcher(message))); - } + @Test + public void givenMsg_whenVerifyUsingMessageMatcher_thenOk() { + MessageApi messageApi = new MessageApi(); + messageApi.setFrom("me"); + messageApi.setTo("you"); + messageApi.setText("Hello, you!"); + + messageController.createMessage(messageApi); + + Message message = new Message(); + message.setFrom("me"); + message.setTo("you"); + message.setText("Hello, you!"); + + verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message))); + } } From b358b17bc00c33d7eeabc0718f37ea90ce5802fa Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:15:33 +0500 Subject: [PATCH 04/39] Updated README.md added link back to the articles: https://www.baeldung.com/java-string-remove-whitespace --- core-java-modules/core-java-string-operations-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-operations-4/README.md b/core-java-modules/core-java-string-operations-4/README.md index ac52ee4ab5..07af6d23c9 100644 --- a/core-java-modules/core-java-string-operations-4/README.md +++ b/core-java-modules/core-java-string-operations-4/README.md @@ -8,3 +8,4 @@ - [Check if a String Ends with a Certain Pattern in Java](https://www.baeldung.com/java-string-ends-pattern) - [Check if a Character is a Vowel in Java](https://www.baeldung.com/java-check-character-vowel) - [How to Truncate a String in Java](https://www.baeldung.com/java-truncating-strings) +- [Remove Whitespace From a String in Java](https://www.baeldung.com/java-string-remove-whitespace) From 47aaa04661679931b6e8a9a5754a5a875b622213 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:25:23 +0500 Subject: [PATCH 05/39] Updated README.md added link back to the article: https://www.baeldung.com/spring-openapi-global-securityscheme --- spring-boot-modules/spring-boot-springdoc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-boot-springdoc/README.md b/spring-boot-modules/spring-boot-springdoc/README.md index 733e31e698..3d0fd19ab1 100644 --- a/spring-boot-modules/spring-boot-springdoc/README.md +++ b/spring-boot-modules/spring-boot-springdoc/README.md @@ -6,3 +6,4 @@ - [Swagger @Api Description Is Deprecated](https://www.baeldung.com/java-swagger-api-description-deprecated) - [Set List of Objects in Swagger API Response](https://www.baeldung.com/java-swagger-set-list-response) - [Configure JWT Authentication for OpenAPI](https://www.baeldung.com/openapi-jwt-authentication) +- [Apply Default Global SecurityScheme in springdoc-openapi](https://www.baeldung.com/spring-openapi-global-securityscheme) From 594cfc0c0ecddf53ea67c9657b20785befd43ee8 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:30:32 +0500 Subject: [PATCH 06/39] Updated README.md added link back to the article: https://www.baeldung.com/maven-snapshot-release-repository --- maven-modules/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/maven-modules/README.md b/maven-modules/README.md index 19f0473a58..29a69d37e4 100644 --- a/maven-modules/README.md +++ b/maven-modules/README.md @@ -8,3 +8,4 @@ This module contains articles about Apache Maven. Please refer to its submodules - [Apache Maven Standard Directory Layout](https://www.baeldung.com/maven-directory-structure) - [Multi-Module Project with Maven](https://www.baeldung.com/maven-multi-module) - [Maven Packaging Types](https://www.baeldung.com/maven-packaging-types) +- [Maven Snapshot Repository vs Release Repository](https://www.baeldung.com/maven-snapshot-release-repository) From e34a4ed1435fdd1a02a0ba7981519bb8f2b2fdd8 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:36:27 +0500 Subject: [PATCH 07/39] Updated README.md added link back to the article: https://www.baeldung.com/spring-reactive-read-flux-into-inputstream --- spring-5-reactive-modules/spring-5-reactive-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-5-reactive-modules/spring-5-reactive-3/README.md b/spring-5-reactive-modules/spring-5-reactive-3/README.md index da44bf98fc..044b3db5f4 100644 --- a/spring-5-reactive-modules/spring-5-reactive-3/README.md +++ b/spring-5-reactive-modules/spring-5-reactive-3/README.md @@ -3,4 +3,5 @@ This module contains articles about reactive Spring 5. - [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging) +- [Reading Flux Into a Single InputStream Using Spring Reactive WebClient](https://www.baeldung.com/spring-reactive-read-flux-into-inputstream) - More articles: [[<-- prev]](../spring-5-reactive-2) From a9115211bcc8aec0a010c0dd85e692257d5cfe5e Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:40:22 +0500 Subject: [PATCH 08/39] Updated README.md added link back to the article: https://www.baeldung.com/spring-jms-testing --- spring-jms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-jms/README.md b/spring-jms/README.md index fdeb64953a..666e32fa4b 100644 --- a/spring-jms/README.md +++ b/spring-jms/README.md @@ -4,3 +4,4 @@ This module contains articles about Spring with JMS ### Relevant Articles: - [Getting Started with Spring JMS](https://www.baeldung.com/spring-jms) +- [Testing Spring JMS](https://www.baeldung.com/spring-jms-testing) From 67c9cfec23b07045b0888849dc78db2489d1ee45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C3=A7im=20Duran?= <49587041+elcim@users.noreply.github.com> Date: Fri, 29 Jul 2022 16:13:54 +0300 Subject: [PATCH 09/39] Bael-5645 - Scanning Java Annotations at Runtime (#12527) * BAEL-5645 - Annotation scanners using Spring context, Spring core, reflections, java reflection, and Jandex libraries are implemented * BAEL-5645 - Library versions are incremented in pom.xml * BAEL-5645 - Some refactoring and indentation adjustments * BAEL-5645 - Revert of annotation value in unit test * BAEL-5645 - Merge with the latest remote version (after resolution of the conflicts) * BAEL-5645 - Some refactoring due to review comments Co-authored-by: elcimduran --- .../scanner/jandexlib/JandexScannerService.java | 8 ++++++-- .../JavaReflectionsScannerService.java | 10 ++++++++-- .../reflectionslib/ReflectionsScannerService.java | 6 ++++-- ...ava => SpringContextAnnotationScannerService.java} | 11 +++++++---- .../SpringCoreAnnotationScannerService.java | 11 +++++++---- .../scanner/SampleAnnotationScannerUnitTest.java | 7 ++++--- 6 files changed, 36 insertions(+), 17 deletions(-) rename spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/{SpringBeanAnnotationScannerService.java => SpringContextAnnotationScannerService.java} (80%) diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java index fc10db223e..7ed41af65d 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java @@ -27,7 +27,9 @@ public class JandexScannerService implements SampleAnnotationScanner { try { final IndexReader reader = new IndexReader(appFile.getInputStream()); Index jandexFile = reader.read(); - final List appAnnotationList = jandexFile.getAnnotations(DotName.createSimple("com.baeldung.annotation.scanner.SampleAnnotation")); + final List appAnnotationList = jandexFile + .getAnnotations(DotName + .createSimple("com.baeldung.annotation.scanner.SampleAnnotation")); List annotatedMethods = new ArrayList<>(); for (AnnotationInstance annotationInstance : appAnnotationList) { if (annotationInstance.target() @@ -48,7 +50,9 @@ public class JandexScannerService implements SampleAnnotationScanner { try { final IndexReader reader = new IndexReader(appFile.getInputStream()); Index jandexFile = reader.read(); - final List appAnnotationList = jandexFile.getAnnotations(DotName.createSimple("com.baeldung.annotation.scanner.SampleAnnotation")); + final List appAnnotationList = jandexFile + .getAnnotations(DotName + .createSimple("com.baeldung.annotation.scanner.SampleAnnotation")); List annotatedClasses = new ArrayList<>(); for (AnnotationInstance annotationInstance : appAnnotationList) { if (annotationInstance.target() diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java index 2833bb1326..76a2293965 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java @@ -1,5 +1,6 @@ package com.baeldung.annotation.scanner.javareflectionlib; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; @@ -37,9 +38,14 @@ public class JavaReflectionsScannerService implements SampleAnnotationScanner { try { Class clazz = ClassLoader.getSystemClassLoader() .loadClass("com.baeldung.annotation.scanner.SampleAnnotatedClass"); - SampleAnnotation classAnnotation = clazz.getAnnotation(SampleAnnotation.class); List annotatedClasses = new ArrayList<>(); - annotatedClasses.add(classAnnotation.name()); + Annotation[] classAnnotations = clazz.getAnnotations(); + for (Annotation annotation : classAnnotations) { + if (annotation.annotationType() + .equals(SampleAnnotation.class)) { + annotatedClasses.add(((SampleAnnotation) annotation).name()); + } + } return Collections.unmodifiableList(annotatedClasses); } catch (ClassNotFoundException e) { throw new UnexpectedScanException(e); diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java index 82a10e21aa..9cee4f19e2 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java @@ -16,7 +16,8 @@ public class ReflectionsScannerService implements SampleAnnotationScanner { @Override public List scanAnnotatedMethods() { Reflections reflections = new Reflections("com.baeldung.annotation.scanner"); - Set methods = reflections.getMethodsAnnotatedWith(SampleAnnotation.class); + Set methods = reflections + .getMethodsAnnotatedWith(SampleAnnotation.class); return methods.stream() .map(method -> method.getAnnotation(SampleAnnotation.class) .name()) @@ -26,7 +27,8 @@ public class ReflectionsScannerService implements SampleAnnotationScanner { @Override public List scanAnnotatedClasses() { Reflections reflections = new Reflections("com.baeldung.annotation.scanner"); - Set> types = reflections.getTypesAnnotatedWith(SampleAnnotation.class); + Set> types = reflections + .getTypesAnnotatedWith(SampleAnnotation.class); return types.stream() .map(clazz -> clazz.getAnnotation(SampleAnnotation.class) .name()) diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringContextAnnotationScannerService.java similarity index 80% rename from spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java rename to spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringContextAnnotationScannerService.java index cd31ae686e..8d52067ccc 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringContextAnnotationScannerService.java @@ -17,7 +17,7 @@ import com.baeldung.annotation.scanner.SampleAnnotationScanner; import com.baeldung.annotation.scanner.ScanNotSupportedException; @Service -public class SpringBeanAnnotationScannerService implements SampleAnnotationScanner { +public class SpringContextAnnotationScannerService implements SampleAnnotationScanner { @Override public List scanAnnotatedMethods() { throw new ScanNotSupportedException(); @@ -25,13 +25,16 @@ public class SpringBeanAnnotationScannerService implements SampleAnnotationScann @Override public List scanAnnotatedClasses() { - ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + ClassPathScanningCandidateComponentProvider provider = + new ClassPathScanningCandidateComponentProvider(false); provider.addIncludeFilter(new AnnotationTypeFilter(SampleAnnotation.class)); - Set beanDefs = provider.findCandidateComponents("com.baeldung.annotation.scanner"); + Set beanDefs = provider + .findCandidateComponents("com.baeldung.annotation.scanner"); List annotatedBeans = new ArrayList<>(); for (BeanDefinition bd : beanDefs) { if (bd instanceof AnnotatedBeanDefinition) { - Map annotAttributeMap = ((AnnotatedBeanDefinition) bd).getMetadata() + Map annotAttributeMap = ((AnnotatedBeanDefinition) bd) + .getMetadata() .getAnnotationAttributes(SampleAnnotation.class.getCanonicalName()); annotatedBeans.add(annotAttributeMap.get("name") .toString()); diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java index f3421fe46d..14542a9104 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java @@ -8,21 +8,24 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.stereotype.Service; import org.springframework.util.ClassUtils; -import com.baeldung.annotation.scanner.SampleAnnotationScanner; import com.baeldung.annotation.scanner.SampleAnnotatedClass; import com.baeldung.annotation.scanner.SampleAnnotation; +import com.baeldung.annotation.scanner.SampleAnnotationScanner; import com.baeldung.annotation.scanner.ScanNotSupportedException; @Service public class SpringCoreAnnotationScannerService implements SampleAnnotationScanner { @Override public List scanAnnotatedMethods() { - final Class userClass = ClassUtils.getUserClass(SampleAnnotatedClass.class); - return Arrays.stream(userClass.getMethods()) - .filter(method -> AnnotationUtils.getAnnotation(method, SampleAnnotation.class) != null) + Class userClass = ClassUtils.getUserClass(SampleAnnotatedClass.class); + List annotatedMethods = Arrays.stream(userClass.getMethods()) + .filter(method -> AnnotationUtils + .getAnnotation(method, SampleAnnotation.class) != null) .map(method -> method.getAnnotation(SampleAnnotation.class) .name()) .collect(Collectors.toList()); + + return annotatedMethods; } @Override diff --git a/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java index 80eca2b4c5..7c3d01b5e8 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java +++ b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java @@ -28,7 +28,8 @@ public class SampleAnnotationScannerUnitTest { assertNotNull(annotatedClasses); assertEquals(4, annotatedClasses.size()); - annotatedClasses.forEach(annotValue -> assertEquals("SampleAnnotatedClass", annotValue)); + annotatedClasses.forEach(annotValue -> assertEquals("SampleAnnotatedClass", + annotValue)); } @Test @@ -41,7 +42,7 @@ public class SampleAnnotationScannerUnitTest { assertNotNull(annotatedMethods); assertEquals(3, annotatedMethods.size()); - annotatedMethods.forEach(annotValue -> assertEquals("annotatedMethod", annotValue)); + annotatedMethods.forEach(annotValue -> assertEquals("annotatedMethod", + annotValue)); } - } From e97b4c899add839de1741a5bd299855540b65401 Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Fri, 29 Jul 2022 19:14:40 +0530 Subject: [PATCH 10/39] JAVA-10376 Code Mismatch | Exploring the Spring 5 WebFlux URL Matching (#12509) * JAVA-10376 Code Mismatch | Exploring the Spring 5 WebFlux URL Matching * JAVA-10376 Code Mismatch | Exploring the Spring 5 WebFlux URL Matching --- ...eSpring5URLPatternUsingRouterFunctions.java | 7 ++++--- .../src/main/resources/resources/test/test.txt | 1 + ...ernUsingRouterFunctionsIntegrationTest.java | 18 ++++++++++++++---- ...ternsUsingHandlerMethodIntegrationTest.java | 14 +++++++++++--- 4 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 spring-5-reactive-modules/spring-5-reactive/src/main/resources/resources/test/test.txt diff --git a/spring-5-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java b/spring-5-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java index 34abada2f1..b7bb53600e 100644 --- a/spring-5-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java +++ b/spring-5-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java @@ -24,11 +24,12 @@ public class ExploreSpring5URLPatternUsingRouterFunctions { private RouterFunction routingFunction() { - return route(GET("/p?ths"), serverRequest -> ok().body(fromValue("/p?ths"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("id")))) - .andRoute(GET("/*card"), serverRequest -> ok().body(fromValue("/*card path was accessed"))) + return route(GET("/t?st"), serverRequest -> ok().body(fromValue("Path /t?st is accessed"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("id")))) + .andRoute(GET("/baeldung/*Id"), serverRequest -> ok().body(fromValue("/baeldung/*Id path was accessed"))) .andRoute(GET("/{var1}_{var2}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("var1") + " , " + serverRequest.pathVariable("var2")))) .andRoute(GET("/{baeldung:[a-z]+}"), serverRequest -> ok().body(fromValue("/{baeldung:[a-z]+} was accessed and baeldung=" + serverRequest.pathVariable("baeldung")))) - .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/"))); + .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/"))) + .and(RouterFunctions.resources("/resources/**", new ClassPathResource("resources/"))); } WebServer start() throws Exception { diff --git a/spring-5-reactive-modules/spring-5-reactive/src/main/resources/resources/test/test.txt b/spring-5-reactive-modules/spring-5-reactive/src/main/resources/resources/test/test.txt new file mode 100644 index 0000000000..30d74d2584 --- /dev/null +++ b/spring-5-reactive-modules/spring-5-reactive/src/main/resources/resources/test/test.txt @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java b/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java index 91721d2cef..a77a67c6ba 100644 --- a/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java +++ b/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java @@ -27,12 +27,12 @@ public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { @Test public void givenRouter_whenGetPathWithSingleCharWildcard_thenGotPathPattern() throws Exception { client.get() - .uri("/paths") + .uri("/test") .exchange() .expectStatus() .isOk() .expectBody(String.class) - .isEqualTo("/p?ths"); + .isEqualTo("Path /t?st is accessed"); } @Test @@ -50,12 +50,12 @@ public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { public void givenRouter_whenGetMultipleCharWildcard_thenGotPathPattern() throws Exception { client.get() - .uri("/wildcard") + .uri("/baeldung/tutorialId") .exchange() .expectStatus() .isOk() .expectBody(String.class) - .isEqualTo("/*card path was accessed"); + .isEqualTo("/baeldung/*Id path was accessed"); } @Test @@ -107,4 +107,14 @@ public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { .isEqualTo("hello"); } + @Test + public void givenRouter_whenAccess_thenGot() throws Exception { + client.get() + .uri("/resources/test/test.txt") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("test"); + } } diff --git a/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/PathPatternsUsingHandlerMethodIntegrationTest.java b/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/PathPatternsUsingHandlerMethodIntegrationTest.java index d4c1cfe4c8..0b4607b54a 100644 --- a/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/PathPatternsUsingHandlerMethodIntegrationTest.java +++ b/spring-5-reactive-modules/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/PathPatternsUsingHandlerMethodIntegrationTest.java @@ -27,13 +27,21 @@ public class PathPatternsUsingHandlerMethodIntegrationTest { @Test public void givenHandlerMethod_whenMultipleURIVariablePattern_then200() { - client.get() - .uri("/spring5/ab/cd") + client.get() + .uri("/spring5/baeldung/tutorial") .exchange() .expectStatus() .is2xxSuccessful() .expectBody() - .equals("/ab/cd"); + .equals("/baeldung/tutorial"); + + client.get() + .uri("/spring5/baeldung") + .exchange() + .expectStatus() + .is2xxSuccessful() + .expectBody() + .equals("/baeldung"); } @Test From 5c8d615fdbf29a8660ae452572a2aefe28fdfd0b Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Fri, 29 Jul 2022 19:32:11 +0530 Subject: [PATCH 11/39] JAVA-12729: rename jackson module --- jackson-modules/{jackson => jackson-core}/README.md | 0 jackson-modules/{jackson => jackson-core}/pom.xml | 4 ++-- .../jackson/deserialization/jacksoninject/Person.java | 0 .../jackson/deserialization/jsonanysetter/Inventory.java | 0 .../jackson/deserialization/jsondeserialize/Book.java | 0 .../jsondeserialize/CustomDateDeserializer.java | 0 .../src/main/java/com/baeldung/jackson/domain/Person.java | 0 .../src/main/java/com/baeldung/jackson/inheritance/Event.java | 0 .../jackson/inheritance/IgnoranceAnnotationStructure.java | 0 .../jackson/inheritance/IgnoranceMixinOrIntrospection.java | 0 .../com/baeldung/jackson/inheritance/ItemIdAddedToUser.java | 0 .../baeldung/jackson/inheritance/ItemIdRemovedFromUser.java | 0 .../jackson/inheritance/SubTypeConstructorStructure.java | 0 .../jackson/inheritance/SubTypeConversionStructure.java | 0 .../jackson/inheritance/TypeInfoAnnotatedStructure.java | 0 .../com/baeldung/jackson/inheritance/TypeInfoStructure.java | 0 .../java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java | 0 .../jackson/jacksonvsgson/ActorJacksonSerializer.java | 0 .../main/java/com/baeldung/jackson/jacksonvsgson/Movie.java | 0 .../baeldung/jackson/jacksonvsgson/MovieWithNullValue.java | 0 .../com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java | 0 .../main/java/com/baeldung/jackson/node/JsonNodeIterator.java | 0 .../java/com/baeldung/jackson/optionalwithjackson/Book.java | 0 .../src/main/resources/example1.json | 0 .../src/main/resources/example2.json | 0 .../{jackson => jackson-core}/src/main/resources/logback.xml | 0 .../src/test/java/com/baeldung/jackson/dtos/Address.java | 0 .../src/test/java/com/baeldung/jackson/dtos/MyDto.java | 0 .../src/test/java/com/baeldung/jackson/dtos/Person.java | 0 .../src/test/java/com/baeldung/jackson/dtos/User.java | 0 .../com/baeldung/jackson/inheritance/IgnoranceUnitTest.java | 0 .../jackson/inheritance/ItemIdRemovedFromUserUnitTest.java | 0 .../baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java | 0 .../jackson/inheritance/TypeInfoInclusionUnitTest.java | 0 .../jackson/jacksonvsgson/JacksonDeserializeUnitTest.java | 0 .../jackson/jacksonvsgson/JacksonSerializeUnitTest.java | 0 .../com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java | 0 .../baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java | 0 .../test/java/com/baeldung/jackson/node/ExampleStructure.java | 0 .../com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java | 0 .../src/test/java/com/baeldung/jackson/node/NodeBean.java | 0 .../java/com/baeldung/jackson/node/NodeOperationUnitTest.java | 0 .../jackson/optionalwithjackson/OptionalTypeUnitTest.java | 0 .../baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java | 0 .../java/com/baeldung/jackson/sandbox/SandboxUnitTest.java | 0 .../test/java/com/baeldung/jackson/sandbox/TestElement.java | 0 .../test/java/com/baeldung/jackson/test/UnitTestSuite.java | 0 .../src/test/java/com/baeldung/jackson/try1/IEntity.java | 0 .../java/com/baeldung/jackson/try1/RestLoaderRequest.java | 0 .../baeldung/jackson/try1/RestLoaderRequestDeserializer.java | 0 .../src/test/resources/author-jsonpropertyorder-schema.json | 0 .../src/test/resources/node_example.json | 0 jackson-modules/pom.xml | 4 ++-- 53 files changed, 4 insertions(+), 4 deletions(-) rename jackson-modules/{jackson => jackson-core}/README.md (100%) rename jackson-modules/{jackson => jackson-core}/pom.xml (96%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Person.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/CustomDateDeserializer.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/domain/Person.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/Event.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/ItemIdAddedToUser.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUser.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJacksonSerializer.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/jacksonvsgson/Movie.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/jacksonvsgson/MovieWithNullValue.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/java/com/baeldung/jackson/optionalwithjackson/Book.java (100%) rename jackson-modules/{jackson => jackson-core}/src/main/resources/example1.json (100%) rename jackson-modules/{jackson => jackson-core}/src/main/resources/example2.json (100%) rename jackson-modules/{jackson => jackson-core}/src/main/resources/logback.xml (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/dtos/Address.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/dtos/MyDto.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/dtos/Person.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/dtos/User.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/inheritance/IgnoranceUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUserUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonDeserializeUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonSerializeUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/node/ExampleStructure.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/node/NodeBean.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/optionalwithjackson/OptionalTypeUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/sandbox/SandboxUnitTest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/sandbox/TestElement.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/try1/IEntity.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java (100%) rename jackson-modules/{jackson => jackson-core}/src/test/resources/author-jsonpropertyorder-schema.json (100%) rename jackson-modules/{jackson => jackson-core}/src/test/resources/node_example.json (100%) diff --git a/jackson-modules/jackson/README.md b/jackson-modules/jackson-core/README.md similarity index 100% rename from jackson-modules/jackson/README.md rename to jackson-modules/jackson-core/README.md diff --git a/jackson-modules/jackson/pom.xml b/jackson-modules/jackson-core/pom.xml similarity index 96% rename from jackson-modules/jackson/pom.xml rename to jackson-modules/jackson-core/pom.xml index 9df0f40874..667e48c88d 100644 --- a/jackson-modules/jackson/pom.xml +++ b/jackson-modules/jackson-core/pom.xml @@ -3,9 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - jackson + jackson-core 0.0.1-SNAPSHOT - jackson + jackson-core com.baeldung diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Person.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Person.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Person.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Person.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/CustomDateDeserializer.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/CustomDateDeserializer.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/CustomDateDeserializer.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/CustomDateDeserializer.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/domain/Person.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/domain/Person.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/domain/Person.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/domain/Person.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/Event.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/Event.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/Event.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/Event.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/ItemIdAddedToUser.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/ItemIdAddedToUser.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/ItemIdAddedToUser.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/ItemIdAddedToUser.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUser.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUser.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUser.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUser.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJackson.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJacksonSerializer.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJacksonSerializer.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJacksonSerializer.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/ActorJacksonSerializer.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/Movie.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/Movie.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/Movie.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/Movie.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/MovieWithNullValue.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/MovieWithNullValue.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/jacksonvsgson/MovieWithNullValue.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jacksonvsgson/MovieWithNullValue.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSON.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java diff --git a/jackson-modules/jackson/src/main/java/com/baeldung/jackson/optionalwithjackson/Book.java b/jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/optionalwithjackson/Book.java similarity index 100% rename from jackson-modules/jackson/src/main/java/com/baeldung/jackson/optionalwithjackson/Book.java rename to jackson-modules/jackson-core/src/main/java/com/baeldung/jackson/optionalwithjackson/Book.java diff --git a/jackson-modules/jackson/src/main/resources/example1.json b/jackson-modules/jackson-core/src/main/resources/example1.json similarity index 100% rename from jackson-modules/jackson/src/main/resources/example1.json rename to jackson-modules/jackson-core/src/main/resources/example1.json diff --git a/jackson-modules/jackson/src/main/resources/example2.json b/jackson-modules/jackson-core/src/main/resources/example2.json similarity index 100% rename from jackson-modules/jackson/src/main/resources/example2.json rename to jackson-modules/jackson-core/src/main/resources/example2.json diff --git a/jackson-modules/jackson/src/main/resources/logback.xml b/jackson-modules/jackson-core/src/main/resources/logback.xml similarity index 100% rename from jackson-modules/jackson/src/main/resources/logback.xml rename to jackson-modules/jackson-core/src/main/resources/logback.xml diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/Address.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/Address.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/MyDto.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/MyDto.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/MyDto.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/MyDto.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/Person.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/Person.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/User.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/User.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/dtos/User.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/dtos/User.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/IgnoranceUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/IgnoranceUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUserUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUserUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUserUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/ItemIdRemovedFromUserUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonDeserializeUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonDeserializeUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonDeserializeUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonDeserializeUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonSerializeUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonSerializeUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonSerializeUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jacksonvsgson/JacksonSerializeUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jsoncompare/JsonCompareUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/jsonnode/GetAllKeysFromJSONUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/ExampleStructure.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/ExampleStructure.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/NodeBean.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/NodeBean.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/optionalwithjackson/OptionalTypeUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/optionalwithjackson/OptionalTypeUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/optionalwithjackson/OptionalTypeUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/optionalwithjackson/OptionalTypeUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/SandboxUnitTest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/SandboxUnitTest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/SandboxUnitTest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/SandboxUnitTest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/TestElement.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/TestElement.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/sandbox/TestElement.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/sandbox/TestElement.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/IEntity.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/IEntity.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/IEntity.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/IEntity.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java diff --git a/jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java b/jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java similarity index 100% rename from jackson-modules/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java rename to jackson-modules/jackson-core/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java diff --git a/jackson-modules/jackson/src/test/resources/author-jsonpropertyorder-schema.json b/jackson-modules/jackson-core/src/test/resources/author-jsonpropertyorder-schema.json similarity index 100% rename from jackson-modules/jackson/src/test/resources/author-jsonpropertyorder-schema.json rename to jackson-modules/jackson-core/src/test/resources/author-jsonpropertyorder-schema.json diff --git a/jackson-modules/jackson/src/test/resources/node_example.json b/jackson-modules/jackson-core/src/test/resources/node_example.json similarity index 100% rename from jackson-modules/jackson/src/test/resources/node_example.json rename to jackson-modules/jackson-core/src/test/resources/node_example.json diff --git a/jackson-modules/pom.xml b/jackson-modules/pom.xml index 14e34a41bf..7a7e08714f 100644 --- a/jackson-modules/pom.xml +++ b/jackson-modules/pom.xml @@ -14,11 +14,11 @@ ../parent-java - - jackson + jackson-annotations jackson-conversions jackson-conversions-2 + jackson-core jackson-custom-conversions jackson-exceptions From 067cddb33e8ebe2b40212b95a79d54c9f565a1b3 Mon Sep 17 00:00:00 2001 From: "thibault.faure" Date: Fri, 29 Jul 2022 21:44:04 +0200 Subject: [PATCH 12/39] Fix failed integration tests --- spring-boot-modules/spring-boot-mvc-3/pom.xml | 7 ------- .../java/com/baeldung/etag/EtagIntegrationTest.java | 2 -- .../DataProducerControllerIntegrationTest.java | 13 ++----------- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/spring-boot-modules/spring-boot-mvc-3/pom.xml b/spring-boot-modules/spring-boot-mvc-3/pom.xml index f2b6c129f8..6b0477cfc8 100644 --- a/spring-boot-modules/spring-boot-mvc-3/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-3/pom.xml @@ -47,11 +47,4 @@ - - - - /src/main/resources - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java index 97de6d06f1..d7b50cb7fb 100644 --- a/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/etag/EtagIntegrationTest.java @@ -9,7 +9,6 @@ import org.assertj.core.util.Preconditions; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.web.server.LocalServerPort; @@ -26,7 +25,6 @@ import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @ComponentScan(basePackageClasses = WebConfig.class) -@EnableAutoConfiguration public class EtagIntegrationTest { @LocalServerPort diff --git a/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/produceimage/DataProducerControllerIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/produceimage/DataProducerControllerIntegrationTest.java index 29f794645a..eb459d88cc 100644 --- a/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/produceimage/DataProducerControllerIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-3/src/test/java/com/baeldung/produceimage/DataProducerControllerIntegrationTest.java @@ -1,32 +1,23 @@ package com.baeldung.produceimage; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import org.springframework.web.context.WebApplicationContext; - @SpringBootTest(classes = ImageApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc public class DataProducerControllerIntegrationTest { @Autowired - private WebApplicationContext webApplicationContext; - private MockMvc mockMvc; - @BeforeEach - public void setup() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); - } - @Test void givenJpgTrue_whenGetImageDynamicType_ThenContentTypeIsJpg() throws Exception { mockMvc.perform(get("/get-image-dynamic-type?jpg=true")) From 300d9408f694d644b28f2652c69c2e60f606884e Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Sat, 30 Jul 2022 06:26:40 +0500 Subject: [PATCH 13/39] Updated README.md Updated link title in README from 'Guide to QuarkusIO' to 'Guide to Quarkus' --- quarkus-modules/quarkus/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quarkus-modules/quarkus/README.md b/quarkus-modules/quarkus/README.md index 94b71dd954..9e45cb1c81 100644 --- a/quarkus-modules/quarkus/README.md +++ b/quarkus-modules/quarkus/README.md @@ -1,4 +1,4 @@ ## Relevant Articles: -- [Guide to QuarkusIO](https://www.baeldung.com/quarkus-io) +- [Guide to Quarkus](https://www.baeldung.com/quarkus-io) - [Testing Quarkus Applications](https://www.baeldung.com/java-quarkus-testing) From be5e772318343aa6fa56d50cf408a0f8a703c2c6 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Sat, 30 Jul 2022 06:34:42 +0500 Subject: [PATCH 14/39] Updated README.md Updated link title in README from 'Sealed Classes and Interfaces in Java 17' to 'Sealed Classes and Interfaces in Java' --- core-java-modules/core-java-17/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-17/README.md b/core-java-modules/core-java-17/README.md index d77a487932..9f39b0289f 100644 --- a/core-java-modules/core-java-17/README.md +++ b/core-java-modules/core-java-17/README.md @@ -5,4 +5,4 @@ - [Introduction to HexFormat in Java 17](https://www.baeldung.com/java-hexformat) - [New Features in Java 17](https://www.baeldung.com/java-17-new-features) - [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators) -- [Sealed Classes and Interfaces in Java 17](https://www.baeldung.com/java-sealed-classes-interfaces) +- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces) From 065846c376798a2d2c0396c38358baae5558fe6a Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Sat, 30 Jul 2022 06:46:34 +0500 Subject: [PATCH 15/39] Updated README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated title from 'Hibernate's “Detached Entity Passed to Persist” Error' to 'Hibernate’s “Detached Entity Passed to Persist” Error' --- persistence-modules/hibernate-exceptions/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/hibernate-exceptions/README.md b/persistence-modules/hibernate-exceptions/README.md index 4acd6cd363..0225d3a753 100644 --- a/persistence-modules/hibernate-exceptions/README.md +++ b/persistence-modules/hibernate-exceptions/README.md @@ -6,4 +6,4 @@ - [Hibernate’s “Object References an Unsaved Transient Instance” Error](https://www.baeldung.com/hibernate-unsaved-transient-instance-error) - [EntityNotFoundException in Hibernate](https://www.baeldung.com/hibernate-entitynotfoundexception) - [Hibernate’s “Not-Null Property References a Null or Transient Value” Error](https://www.baeldung.com/hibernate-not-null-error) -- [Hibernate's “Detached Entity Passed to Persist” Error](https://www.baeldung.com/hibernate-detached-entity-passed-to-persist) +- [Hibernate’s “Detached Entity Passed to Persist” Error](https://www.baeldung.com/hibernate-detached-entity-passed-to-persist) From 7602a36fae19e2f33847e1d4a361a2e035dc5b8b Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Sat, 30 Jul 2022 12:12:16 +0530 Subject: [PATCH 16/39] JAVA-13614 Look into How to Read HTTP Headers in Spring REST Controllers article --- .../controller/ReadHeaderRestController.java | 7 +++++-- ...ReadHeaderRestControllerIntegrationTest.java | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) 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 6a0f3b6a0d..ff4d0eea58 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 @@ -1,6 +1,8 @@ package com.baeldung.spring.headers.controller; import java.net.InetSocketAddress; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; @@ -24,9 +26,10 @@ public class ReadHeaderRestController { } @GetMapping("/greeting") - public ResponseEntity greeting(@RequestHeader(value = "accept-language") String language) { + public ResponseEntity greeting(@RequestHeader(value = HttpHeaders.ACCEPT_LANGUAGE) String language) { String greeting = ""; - String firstLanguage = (language.length() > 1 ? language.substring(0, 2) : language); + List ranges = Locale.LanguageRange.parse(language); + String firstLanguage = ranges.get(0).getRange(); switch (firstLanguage) { case "es": greeting = "Hola!"; diff --git a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java index 6f94004cc7..1641939b67 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java +++ b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; import org.springframework.test.web.servlet.MockMvc; @@ -51,10 +52,24 @@ public class ReadHeaderRestControllerIntegrationTest { @Test public void whenGetRequestSentToGreeting_thenStatusOKAndGreetingReturned() throws Exception { - mockMvc.perform(get("/greeting").header("accept-language", "de")) + mockMvc.perform(get("/greeting").header(HttpHeaders.ACCEPT_LANGUAGE, "de")) .andExpect(status().isOk()) .andExpect(content().string("Hallo!")); } + + @Test + public void whenPrioritizedListGetRequestSentToGreeting_thenStatusOKAndGreetingReturned() throws Exception { + mockMvc.perform(get("/greeting").header(HttpHeaders.ACCEPT_LANGUAGE, "fr,en,de")) + .andExpect(status().isOk()) + .andExpect(content().string("Bonjour!")); + } + + @Test + public void whenWeightedListGetRequestSentToGreeting_thenStatusOKAndGreetingReturned() throws Exception { + mockMvc.perform(get("/greeting").header(HttpHeaders.ACCEPT_LANGUAGE, "Accept-Language: es; q=1.0, de; q=0.5")) + .andExpect(status().isOk()) + .andExpect(content().string("Hola!")); + } @Test public void whenGetRequestSentToDouble_thenStatusOKAndCorrectResultReturned() throws Exception { From ef758acef0b9852575bf483981923c345caadff4 Mon Sep 17 00:00:00 2001 From: lalitrajput72 <31237283+lalitrajput72@users.noreply.github.com> Date: Sat, 30 Jul 2022 16:09:02 +0530 Subject: [PATCH 17/39] [BAEL-5622] static vs instance initializer block (#12271) * Deep copy vs Shallow copy Code commit * Static and instance block * Deep copy branch chanaged from master to other * static vs instance block * Update InstanceBlockExample.java * Update StaticBlockExample.java Co-authored-by: Lalit Rajput Co-authored-by: paritoshsunny --- .../instanceblock/InstanceBlockExample.java | 22 +++++++++++++++++++ .../staticblock/StaticBlockExample.java | 17 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/instanceblock/InstanceBlockExample.java create mode 100644 core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/staticblock/StaticBlockExample.java diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/instanceblock/InstanceBlockExample.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/instanceblock/InstanceBlockExample.java new file mode 100644 index 0000000000..c17fd8d3e6 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/instanceblock/InstanceBlockExample.java @@ -0,0 +1,22 @@ +package com.baeldung.initializerblock.instanceblock; + +public class InstanceBlockExample { + + { + System.out.println("Instance initializer block 1"); + } + + { + System.out.println("Instance initializer block 2"); + } + + public InstanceBlockExample() { + System.out.println("Class constructor"); + } + + public static void main(String[] args) { + InstanceBlockExample iib = new InstanceBlockExample(); + System.out.println("Main Method"); + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/staticblock/StaticBlockExample.java b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/staticblock/StaticBlockExample.java new file mode 100644 index 0000000000..a409b6d7c8 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors/src/main/java/com/baeldung/initializerblock/staticblock/StaticBlockExample.java @@ -0,0 +1,17 @@ +package com.baeldung.initializerblock.staticblock; + +public class StaticBlockExample { + + static { + System.out.println("static block 1"); + } + + static { + System.out.println("static block 2"); + } + + public static void main(String[] args) { + System.out.println("Main Method"); + } +} + From d0ba47e75dede5fa71c22bc0ab0e831ec41edf1d Mon Sep 17 00:00:00 2001 From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com> Date: Sat, 30 Jul 2022 14:22:59 +0200 Subject: [PATCH 18/39] BAEL-5643 : Replace at Specific Index in Java ArrayList (#12539) --- .../ReplaceUsingIndexInArrayListUnitTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/replace/ReplaceUsingIndexInArrayListUnitTest.java diff --git a/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/replace/ReplaceUsingIndexInArrayListUnitTest.java b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/replace/ReplaceUsingIndexInArrayListUnitTest.java new file mode 100644 index 0000000000..ad6d0fee43 --- /dev/null +++ b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/replace/ReplaceUsingIndexInArrayListUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.list.replace; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class ReplaceUsingIndexInArrayListUnitTest { + + private static final List EXPECTED = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + + @Test void givenArrayList_updateUsingSet() { + List aList = new ArrayList<>(Arrays.asList(1, 2, 7, 4, 5)); + aList.set(2, 3); + assertThat(aList).isEqualTo(EXPECTED); + } +} \ No newline at end of file From a313c855d32b0ac6e7ee417d104ee8dab10c6304 Mon Sep 17 00:00:00 2001 From: Thiago dos Santos Hora Date: Sat, 30 Jul 2022 14:26:16 +0200 Subject: [PATCH 19/39] [BAEL-5631] Quarkus vs Spring boot improvements (#12520) * Initial impl * Update framework versions testing from jm to wrk * Add hyperfoil * Add hyperfoil read me --- .../quarkus-vs-springboot/README.md | 54 +++- .../hyperfoil/docker_run.sh | 13 + .../hyperfoil/volume/benchmark.hf.yaml | 86 ++++++ .../{ => hyperfoil/volume}/cities.csv | 0 .../quarkus-vs-springboot/jmeter/cities.csv | 136 +++++++++ .../{ => jmeter}/load_test.jmx | 0 .../run_test_jmeter.sh} | 0 .../quarkus-project/build.sh | 8 +- .../quarkus-project/pom.xml | 277 +++++++++--------- .../src/main/docker/Dockerfile.jvm | 3 +- .../src/main/docker/quarkus.yml | 30 +- .../baeldung/quarkus_project/ZipCodeRepo.java | 4 +- .../quarkus_project/ZipCodeResource.java | 16 +- .../src/main/resources/application.properties | 13 +- .../spring-project/build.sh | 11 + .../spring-project/build_jvm_docker.sh | 6 - .../spring-project/pom.xml | 229 ++++++++++----- .../src/main/docker/Dockerfile.jvm | 12 - .../spring-project/src/main/docker/spring.yml | 30 +- .../com/baeldung/spring_project/Startup.java | 6 +- .../baeldung/spring_project/ZipCodeApi.java | 24 +- .../src/main/resources/application.properties | 12 +- .../baeldung/spring_project/StartupIT.java | 13 +- .../quarkus-vs-springboot/wrk/cities.csv | 136 +++++++++ .../quarkus-vs-springboot/wrk/generator.lua | 65 ++++ .../quarkus-vs-springboot/wrk/get_by_city.lua | 79 +++++ .../quarkus-vs-springboot/wrk/get_zipcode.lua | 77 +++++ .../quarkus-vs-springboot/wrk/json.lua | 133 +++++++++ .../wrk/post_zipcode.lua | 73 +++++ .../quarkus-vs-springboot/wrk/run_test_wrk.sh | 14 + 30 files changed, 1258 insertions(+), 302 deletions(-) create mode 100644 quarkus-modules/quarkus-vs-springboot/hyperfoil/docker_run.sh create mode 100644 quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/benchmark.hf.yaml rename quarkus-modules/quarkus-vs-springboot/{ => hyperfoil/volume}/cities.csv (100%) create mode 100644 quarkus-modules/quarkus-vs-springboot/jmeter/cities.csv rename quarkus-modules/quarkus-vs-springboot/{ => jmeter}/load_test.jmx (100%) rename quarkus-modules/quarkus-vs-springboot/{run_test.sh => jmeter/run_test_jmeter.sh} (100%) create mode 100755 quarkus-modules/quarkus-vs-springboot/spring-project/build.sh delete mode 100644 quarkus-modules/quarkus-vs-springboot/spring-project/build_jvm_docker.sh delete mode 100644 quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/Dockerfile.jvm create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/cities.csv create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/generator.lua create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/get_by_city.lua create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/get_zipcode.lua create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/json.lua create mode 100644 quarkus-modules/quarkus-vs-springboot/wrk/post_zipcode.lua create mode 100755 quarkus-modules/quarkus-vs-springboot/wrk/run_test_wrk.sh diff --git a/quarkus-modules/quarkus-vs-springboot/README.md b/quarkus-modules/quarkus-vs-springboot/README.md index 05eaabb923..13c0b8ab5f 100644 --- a/quarkus-modules/quarkus-vs-springboot/README.md +++ b/quarkus-modules/quarkus-vs-springboot/README.md @@ -6,6 +6,9 @@ To follow this tutorial, you will need the following things: - Maven (Embedded, IDE, or local installation) - Docker (https://www.docker.com/) - Jmeter (https://jmeter.apache.org/) +- wrk (https://github.com/wg/wrk) +- hyperfoil (https://hyperfoil.io/) +- lua (https://www.lua.org/) To create this test, I used some custom features from Jmeter. You can install the Jmeter plugin manager here: https://loadium.com/blog/how-to-install-use-jmeter-plugin. After that, please install the following plugins: @@ -17,31 +20,32 @@ The test file is `load_test.jmx` in case of any change need. You can open it wit $jmeter_home/bin/jmeter -n -t load_test.jmx -l log.csv -e -o ./report ``` -Just remember to change the variable `jmeter_home` with the path to the JMeter folder. The path to the data files is relative, so either keep them in the same folder as the test or use Jmeter GUI to change it. +Just remember to change the variable `jmeter_home` with the path to the JMeter folder. The path to the data files is relative, so either keep them in the same folder as the test or use Jmeter GUI to change it. Rememeber that as mentioned in the article, we cannot consider the response times recorded by Jmeter due to the Coordinated Omission Problem. Open the VisualVM application and select your application to start monitoring before running the test, and of course, start the sample application first. ## Spring Boot To build the application, you only need to run the following command in the Spring project root: ``` -./mvnw package -f pom.xml +./mvnw clean package -f pom.xml ``` Or this one in case you want to build the native one: ``` -./mvnw -DskipTests package -Pnative -f pom.xml +./mvnw clean package -Pnative -f pom.xml ``` In this case, you will need to have the `GRAALVM_HOME` env variable defined. You only need this if you want to build the image locally. Otherwise, you can build it using docker by leveraging the Spring Boot maven plugin. It will pull a docker image of the GraalVM, and with that, it will create the native image of the app. To do that, run: ``` -./mvnw spring-boot:build-image +./mvnw clean package spring-boot:build-image -Pnative -f pom.xml ``` -You can also create a docker image with the JVM version of the app running the script `build_jvm_docker.sh` or: +You can also create a docker image with the JVM version one of the app running the script `build.sh` or: ``` -docker build -f src/main/docker/Dockerfile.jvm -t spring-project:0.1-SNAPSHOT . +./mvnw clean package spring-boot:build-image -f pom.xml + ``` -You can execute the script `start_app.sh` or `start_jvm.sh` to run the application locally. In this case, you will need the Postgres DB. You can run it in docker with the command: +You can execute the script `start_app.sh` or `start_jvm.sh` to run the application locally. In this case, you will need the Mysql DB. You can run it in docker with the command: ``` -docker run -e POSTGRES_PASSWORD=example -p 5432:5432 postgres +docker run --name mysqldb --network=host -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=baeldung -d mysql:5.7.38 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ``` You can also run both application and DB from docker, using: ``` @@ -67,7 +71,7 @@ And to the JVM version: To start the application locally, use either the scripts `start_app.sh` and `start_jvm.sh` with the docker DB: ``` -docker run -e POSTGRES_PASSWORD=example -p 5432:5432 postgres +docker run --name mysqldb --network=host -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=baeldung -d mysql:5.7.38 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ``` Or use the script to build the docker image of the application, running: ```bash @@ -94,6 +98,38 @@ docker-compose -f src/main/docker/quarkus.yml up Now you have all you need to reproduce the tests with your machine. +## Wrk +Another option to execute the load test is to use the wrk. This library is capable of generation a pretty high load only using a single core. To install it you only have to checkout the project compile it (using make) and define the `wrk_home` envvar. To run the test use: + +``` +./run_test_wrk.sh +``` +You will need to have installed lua in your machine. + +### Tips +If you want to run the applications in your machine you can use the following command to restrict the CPUs available to the app: + +``` +cpulimit -l 300 -p ## 300 means at most 3 cores. +``` + +This will make sure the load is on the application and not in the DB. +## Hyperfoil + +To the hyperfoil test to get a report regarding the performance of the application, its throughput and response time. You can run the `docker_run.sh` from the hyperfoil folder, or the following: + +``` +docker run -it -v volume:/benchmarks:Z -v tmp/reports:/tmp/reports:Z --network=host quay.io/hyperfoil/hyperfoil cli +``` +And then: +``` +start-local && upload /benchmarks/benchmark.hf.yaml && run benchmark +``` +Optionally, we can extract a html report from it, by running: +``` +report --destination=/tmp/reports +``` + ### Relevant Articles: - [Spring Boot vs Quarkus](https://www.baeldung.com/spring-boot-vs-quarkus) diff --git a/quarkus-modules/quarkus-vs-springboot/hyperfoil/docker_run.sh b/quarkus-modules/quarkus-vs-springboot/hyperfoil/docker_run.sh new file mode 100644 index 0000000000..ee0ee35a29 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/hyperfoil/docker_run.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +docker run -it -v $SCRIPTPATH/volume:/benchmarks:Z -v $SCRIPTPATH/tmp/reports:/tmp/reports:Z --network=host quay.io/hyperfoil/hyperfoil cli + +#start-local && upload /benchmarks/benchmark.hf.yaml && run benchmark + +# step 1 run: start-local +# step 2 run (Run this every time the file is modified): upload /benchmarks/benchmark.hf.yaml +# step 3 run: run benchmark +# step 4 run: stats +# step 5 run: report --destination=/tmp/reports diff --git a/quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/benchmark.hf.yaml b/quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/benchmark.hf.yaml new file mode 100644 index 0000000000..598c61249e --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/benchmark.hf.yaml @@ -0,0 +1,86 @@ +name: benchmark +http: + host: http://localhost:8080 + sharedConnections: 100 +phases: + - main: + constantRate: + startAfter: rampup + usersPerSec: 3300 + maxSessions: 6000 + duration: 5m + forks: + - post_zipcode: &post_zipcode + scenario: + - fetchIndex: + - randomCsvRow: + file: /benchmarks/zip_code_database.csv + removeQuotes: true + columns: + 0: zip + 1: type + 3: city + 6: state + 7: county + 8: timezone + - httpRequest: + sla: + - blockedRatio: 500 + POST: /zipcode + headers: + Content-Type: application/json;charset=UTF-8 + Accept: application/json + body: | + { + "zip" : "${zip}", + "type" : "${type}", + "city" : "${city}", + "state" : "${state}", + "county" : "${county}", + "timezone" : "${timezone}" + } + - get_zipcode: &get_zipcode + scenario: + - fetchIndex: + - randomCsvRow: + file: /benchmarks/zip_code_database.csv + removeQuotes: true + columns: + 0: zipcode + - httpRequest: + sla: + - blockedRatio: 500 + headers: + accept: application/json + GET: /zipcode/${zipcode} + - get_zipcode_by_city: &get_zipcode_by_city + scenario: + - fetchDetails: + - randomCsvRow: + file: /benchmarks/cities.csv + removeQuotes: true + columns: + 0: city + - httpRequest: + sla: + - blockedRatio: 500 + headers: + accept: application/json + GET: /zipcode/by_city?city=${city} + - spike: + constantRate: + startAfter: main + usersPerSec: 4400 + duration: 2m + forks: + - get_zipcode_by_city: *get_zipcode_by_city + - get_zipcode: *get_zipcode + + - rampup: + increasingRate: + initialUsersPerSec: 3 + targetUsersPerSec: 2500 + duration: 1m + forks: + - post_zipcode: *post_zipcode + - get_zipcode: *get_zipcode diff --git a/quarkus-modules/quarkus-vs-springboot/cities.csv b/quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/cities.csv similarity index 100% rename from quarkus-modules/quarkus-vs-springboot/cities.csv rename to quarkus-modules/quarkus-vs-springboot/hyperfoil/volume/cities.csv diff --git a/quarkus-modules/quarkus-vs-springboot/jmeter/cities.csv b/quarkus-modules/quarkus-vs-springboot/jmeter/cities.csv new file mode 100644 index 0000000000..3b7016f3b5 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/jmeter/cities.csv @@ -0,0 +1,136 @@ +Holtsville +Adjuntas +Aguada +Aguadilla +Maricao +Anasco +Angeles +Arecibo +Bajadero +Barceloneta +Boqueron +Cabo Rojo +Penuelas +Camuy +Castaner +Rosario +Sabana Grande +Ciales +Utuado +Dorado +Ensenada +Florida +Garrochales +Guanica +Guayanilla +Hatillo +Hormigueros +Isabela +Jayuya +Lajas +Lares +Las Marias +Manati +Moca +Rincon +Quebradillas +Mayaguez +San German +San Sebastian +Morovis +Sabana Hoyos +San Antonio +Vega Alta +Vega Baja +Yauco +Aguas Buenas +Aguirre +Aibonito +Maunabo +Arroyo +Mercedita +Ponce +Naguabo +Naranjito +Orocovis +Palmer +Patillas +Caguas +Canovanas +Ceiba +Cayey +Fajardo +Cidra +Puerto Real +Punta Santiago +Roosevelt Roads +Rio Blanco +Rio Grande +Salinas +San Lorenzo +Santa Isabel +Vieques +Villalba +Yabucoa +Coamo +Las Piedras +Loiza +Luquillo +Culebra +Juncos +Gurabo +Coto Laurel +Comerio +Corozal +Guayama +La Plata +Humacao +Barranquitas +Juana Diaz +St Thomas +Christiansted +St John +Frederiksted +Kingshill +San Juan +Fort Buchanan +Toa Baja +Sabana Seca +Toa Alta +Bayamon +Catano +Guaynabo +Trujillo Alto +Saint Just +Carolina +Agawam +Amherst +Barre +Belchertown +Blandford +Bondsville +Brimfield +Chester +Chesterfield +Chicopee +Cummington +Easthampton +East Longmeadow +East Otis +Feeding Hills +Gilbertville +Goshen +Granby +Granville +Hadley +Hampden +Hardwick +Hatfield +Haydenville +Holyoke +Huntington +Leeds +Leverett +Ludlow +Monson +North Amherst \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/load_test.jmx b/quarkus-modules/quarkus-vs-springboot/jmeter/load_test.jmx similarity index 100% rename from quarkus-modules/quarkus-vs-springboot/load_test.jmx rename to quarkus-modules/quarkus-vs-springboot/jmeter/load_test.jmx diff --git a/quarkus-modules/quarkus-vs-springboot/run_test.sh b/quarkus-modules/quarkus-vs-springboot/jmeter/run_test_jmeter.sh similarity index 100% rename from quarkus-modules/quarkus-vs-springboot/run_test.sh rename to quarkus-modules/quarkus-vs-springboot/jmeter/run_test_jmeter.sh diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/build.sh b/quarkus-modules/quarkus-vs-springboot/quarkus-project/build.sh index 85761adab0..22b6d5c9d4 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/build.sh +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/build.sh @@ -2,12 +2,14 @@ SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -./mvnw quarkus:add-extension -Dextensions=container-image-docker +mvn quarkus:add-extension -Dextensions=container-image-docker if [ "$1" = "native" ]; then - ./mvnw package -Pnative -Dquarkus.native.container-build=true -f $SCRIPTPATH/pom.xml && + mvn clean package -Pnative -Dquarkus.native.container-build=true -f $SCRIPTPATH/pom.xml && docker build -f $SCRIPTPATH/src/main/docker/Dockerfile.native -t quarkus-project:0.1-SNAPSHOT $SCRIPTPATH/. +elif [ "$1" = "local-native" ]; then + mvn clean package -DskipTests -Pnative -f $SCRIPTPATH/pom.xml else - ./mvnw package -Dquarkus.container-build=true -f $SCRIPTPATH/pom.xml && + mvn clean package -Dquarkus.container-build=true -f $SCRIPTPATH/pom.xml && docker build -f $SCRIPTPATH/src/main/docker/Dockerfile.jvm -t quarkus-project:0.1-SNAPSHOT $SCRIPTPATH/. fi \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/pom.xml b/quarkus-modules/quarkus-vs-springboot/quarkus-project/pom.xml index eeeb9d3256..8f28fde4a6 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/pom.xml @@ -1,150 +1,143 @@ - - 4.0.0 - quarkus-project - 0.1-SNAPSHOT - - - com.baeldung - quarkus-vs-springboot - 1.0-SNAPSHOT - - - - - - ${quarkus.platform.group-id} - ${quarkus.platform.artifact-id} - ${quarkus.platform.version} - pom - import - - - - + 4.0.0 + + com.baeldung + quarkus-vs-springboot + 1.0-SNAPSHOT + + quarkus-project + 0.1-SNAPSHOT + + 3.10.1 + true + 11 + 11 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 2.9.2.Final + 3.0.0-M6 + + - - io.quarkus - quarkus-hibernate-reactive-panache - - - io.quarkus - quarkus-resteasy-reactive - - - io.quarkus - quarkus-resteasy-reactive-jackson - - - io.quarkus - quarkus-reactive-pg-client - - - io.quarkus - quarkus-arc - - - io.quarkus - quarkus-container-image-docker - - - io.quarkus - quarkus-junit5 - test - - - io.rest-assured - rest-assured - test - + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + - - + + + + io.quarkus + quarkus-hibernate-reactive-panache + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.quarkus + quarkus-reactive-mysql-client + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-container-image-docker + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + ${maven.compiler.parameters} + + + + maven-surefire-plugin + ${surefire-plugin.version} + + false + + org.jboss.logmanager.LogManager + + + + + + + + native + + + native + + + - - ${quarkus.platform.group-id} - quarkus-maven-plugin - ${quarkus.platform.version} - true - - - - build - generate-code - generate-code-tests - - - - - - maven-compiler-plugin - ${compiler-plugin.version} + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + - ${maven.compiler.parameters} + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + - - - maven-surefire-plugin - ${surefire-plugin.version} - - false - - org.jboss.logmanager.LogManager - - - + + + - - - - native - - - native - - - - - - maven-failsafe-plugin - ${surefire-plugin.version} - - - - integration-test - verify - - - - ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager - - - - - - - - - -H:+AllowVMInspection - native - - - - - - 3.8.1 - true - 11 - 11 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 2.2.2.Final - 3.0.0-M4 - - - \ No newline at end of file + + + -H:+AllowVMInspection + native + + + + diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/Dockerfile.jvm b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/Dockerfile.jvm index e5d6d4d851..63ba538a4a 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/Dockerfile.jvm +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/Dockerfile.jvm @@ -41,7 +41,8 @@ RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. -ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=5000 -Dcom.sun.management.jmxremote.rmi.port=5001 -Dcom.sun.management.jmxremote.host=0.0.0.0 -Djava.rmi.server.hostname=0.0.0.0" + # We make four distinct layers so if there are application changes the library layers can be re-used COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ COPY --chown=1001 target/quarkus-app/*.jar /deployments/ diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/quarkus.yml b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/quarkus.yml index 00bdcf9292..60e35b6cca 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/quarkus.yml +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/docker/quarkus.yml @@ -1,23 +1,25 @@ version: '3.1' - services: db: - image: postgres + image: mysql:5.7.38 ports: - - '5432:5432' + - '3306:3306' environment: - POSTGRES_PASSWORD: example + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: baeldung + command: [ 'mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci' ] + healthcheck: + test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD app: image: quarkus-project:0.1-SNAPSHOT - ports: - - '8080:8080' + network_mode: "host" environment: - DB_URL: postgresql://db:5432/postgres - links: - - "db" + DB_URL: mysql://localhost:3306/baeldung?useSSL=true&requireSSL=true + HOST_HOSTNAME: ${EXTERNAL_IP} depends_on: - - "db" -networks: - default: - driver: bridge - + db: + condition: service_healthy + deploy: + resources: + limits: + cpus: '3.00' diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeRepo.java b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeRepo.java index 74f46c33ea..f6736a6e9e 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeRepo.java +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeRepo.java @@ -1,6 +1,7 @@ package com.baeldung.quarkus_project; import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase; +import io.quarkus.hibernate.reactive.panache.common.runtime.ReactiveTransactional; import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; @@ -13,7 +14,8 @@ public class ZipCodeRepo implements PanacheRepositoryBase { return find("city = ?1", city).stream(); } + @ReactiveTransactional public Uni save(ZipCode zipCode) { - return zipCode.persistAndFlush(); + return zipCode.persist(); } } diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeResource.java b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeResource.java index b4d41fd855..cb9b0226f3 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeResource.java +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/java/com/baeldung/quarkus_project/ZipCodeResource.java @@ -2,9 +2,8 @@ package com.baeldung.quarkus_project; import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; -import org.jboss.logging.Logger; -import javax.transaction.Transactional; +import javax.persistence.PersistenceException; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @@ -22,7 +21,7 @@ public class ZipCodeResource { @GET @Path("/{zipcode}") public Uni findById(@PathParam("zipcode") String zipcode) { - return zipRepo.findById(zipcode); + return getById(zipcode); } @GET @@ -32,12 +31,17 @@ public class ZipCodeResource { } @POST - @Transactional public Uni create(ZipCode zipCode) { - return zipRepo.findById(zipCode.getZip()) + return getById(zipCode.getZip()) .onItem() .ifNull() - .switchTo(createZipCode(zipCode)); + .switchTo(createZipCode(zipCode)) + .onFailure(PersistenceException.class) + .recoverWithUni(() -> getById(zipCode.getZip())); + } + + private Uni getById(String zipCode) { + return zipRepo.findById(zipCode); } private Uni createZipCode(ZipCode zipCode) { diff --git a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/resources/application.properties b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/resources/application.properties index 918a129500..7c1bee8da5 100644 --- a/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/resources/application.properties +++ b/quarkus-modules/quarkus-vs-springboot/quarkus-project/src/main/resources/application.properties @@ -1,9 +1,12 @@ -quarkus.datasource.db-kind=postgresql -quarkus.datasource.username=postgres -quarkus.datasource.password=example +quarkus.datasource.db-kind=mysql +quarkus.datasource.username=root +quarkus.datasource.password=root -quarkus.datasource.reactive.url=${DB_URL:postgresql://localhost:5432/postgres} -quarkus.datasource.reactive.max-size=20 +quarkus.datasource.reactive.url=${DB_URL:mysql://localhost:3306/baeldung?useSSL=true&requireSSL=true} +quarkus.datasource.reactive.max-size=95 +quarkus.datasource.reactive.mysql.ssl-mode=required #quarkus.hibernate-orm.log.sql=true quarkus.hibernate-orm.database.generation=drop-and-create +quarkus.native.enable-vm-inspection=true +quarkus.datasource.reactive.trust-all=true \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/build.sh b/quarkus-modules/quarkus-vs-springboot/spring-project/build.sh new file mode 100755 index 0000000000..d8e131d244 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +if [ "$1" = "native" ]; then + mvn clean package -DskipTests spring-boot:build-image -Pnative -f $SCRIPTPATH/pom.xml +elif [ "$1" = "local-native" ]; then + mvn clean package -DskipTests -Plocal-native -f $SCRIPTPATH/pom.xml +else + mvn clean package -DskipTests spring-boot:build-image -f $SCRIPTPATH/pom.xml +fi \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/build_jvm_docker.sh b/quarkus-modules/quarkus-vs-springboot/spring-project/build_jvm_docker.sh deleted file mode 100644 index c7ee730ec7..0000000000 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/build_jvm_docker.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" - -docker build -f $SCRIPTPATH/src/main/docker/Dockerfile.jvm -t spring-project:0.1-SNAPSHOT $SCRIPTPATH/. - diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml index 7f0fa4c8c6..408c223e9f 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml @@ -10,8 +10,8 @@ org.springframework.boot spring-boot-starter-parent - 2.6.0 - + 2.6.9 + @@ -29,14 +29,9 @@ ${spring-native.version} - io.r2dbc - r2dbc-postgresql - runtime - - - org.postgresql - postgresql - runtime + com.github.jasync-sql + jasync-r2dbc-mysql + 2.0.8 org.springframework.boot @@ -48,131 +43,210 @@ reactor-test test + + + org.testcontainers + testcontainers + test + + + + org.testcontainers + r2dbc + test + + + + org.testcontainers + mysql + test + + + + mysql + mysql-connector-java + test + + + + org.testcontainers + junit-jupiter + test + + + + + + org.testcontainers + testcontainers-bom + 1.17.2 + pom + import + + + + org.springframework.boot spring-boot-maven-plugin - ${repackage.classifier} + exec + + true + paketobuildpacks/builder:tiny - true + false + true - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - + maven-surefire-plugin + ${surefire-plugin.version} + + + **/*IT + + - spring-releases - Spring Releases + spring-release + Spring release https://repo.spring.io/release - - false - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - spring-releases - Spring Releases + spring-release + Spring release https://repo.spring.io/release - - false - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - native - - exec - 0.9.3 - - org.graalvm.buildtools - junit-platform-native - ${native-buildtools.version} + org.junit.platform + junit-platform-launcher + test + + org.springframework.boot + spring-boot-maven-plugin + + + true + + + paketobuildpacks/builder:tiny + + true + true + + + + + + org.springframework.experimental + spring-aot-maven-plugin + + + test-generate + + test-generate + + + + generate + + generate + + + + + + + + + local-native + + exec + 0.9.11 + + + + org.junit.platform + junit-platform-launcher + test + + + + + + org.springframework.experimental + spring-aot-maven-plugin + + + test-generate + + test-generate + + + + generate + + generate + + + + org.graalvm.buildtools native-maven-plugin ${native-buildtools.version} + true -H:+AllowVMInspection - - test-native - test - - test - - build-native - package build + package + + + test-native + + test + + test org.apache.maven.plugins maven-surefire-plugin + 3.0.0-M6 -DspringAot=true -agentlib:native-image-agent=access-filter-file=src/test/resources/access-filter.json,config-merge-dir=target/classes/META-INF/native-image @@ -185,9 +259,8 @@ 11 - - 0.11.0-RC1 - 2.17.1 + 0.12.1 + 3.0.0-M6 - \ No newline at end of file + diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/Dockerfile.jvm b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/Dockerfile.jvm deleted file mode 100644 index ca3f3cca76..0000000000 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/Dockerfile.jvm +++ /dev/null @@ -1,12 +0,0 @@ -FROM openjdk:11 - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -COPY --chown=1001 target/spring-project-0.1-SNAPSHOT-exec.jar /spring-app/ - -WORKDIR /spring-app - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["java", "-jar", "spring-project-0.1-SNAPSHOT-exec.jar" ] \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/spring.yml b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/spring.yml index 2214e0a898..347b5dfe2f 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/spring.yml +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/docker/spring.yml @@ -2,21 +2,25 @@ version: '3.1' services: db: - image: postgres + image: mysql:5.7.38 ports: - - '5432:5432' + - '3306:3306' environment: - POSTGRES_PASSWORD: example + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: baeldung + command: [ 'mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci' ] + healthcheck: + test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD app: - image: spring-project:0.1-SNAPSHOT - ports: - - '8080:8080' + image: docker.io/library/spring-project:0.1-SNAPSHOT + network_mode: "host" environment: - DB_URL: r2dbc:postgresql://db:5432/postgres - links: - - "db" + DB_URL: r2dbc:mysql://localhost:3306/baeldung?useSSL=true&requireSSL=true + HOST_HOSTNAME: ${EXTERNAL_IP} depends_on: - - "db" -networks: - default: - driver: bridge \ No newline at end of file + db: + condition: service_healthy + deploy: + resources: + limits: + cpus: '3.00' diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/Startup.java b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/Startup.java index 48cf7e8ed1..e8544da8db 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/Startup.java +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/Startup.java @@ -1,21 +1,22 @@ package com.baeldung.spring_project; -import com.baeldung.spring_project.domain.ZIPRepo; import io.r2dbc.spi.ConnectionFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ByteArrayResource; +import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; import org.springframework.r2dbc.connection.R2dbcTransactionManager; import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer; import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator; import org.springframework.transaction.ReactiveTransactionManager; @SpringBootApplication +@EnableR2dbcRepositories public class Startup { public static void main(String[] args) { - SpringApplication.run(Startup.class, args).getBean(ZIPRepo.class).findById(""); + SpringApplication.run(Startup.class, args); } @Bean @@ -34,4 +35,5 @@ public class Startup { @Bean ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) { return new R2dbcTransactionManager(connectionFactory); } + } diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/ZipCodeApi.java b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/ZipCodeApi.java index 263ce67e21..8d1f07b7b9 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/ZipCodeApi.java +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/java/com/baeldung/spring_project/ZipCodeApi.java @@ -2,11 +2,14 @@ package com.baeldung.spring_project; import com.baeldung.spring_project.domain.ZIPRepo; import com.baeldung.spring_project.domain.ZipCode; -import org.springframework.transaction.annotation.Transactional; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.r2dbc.UncategorizedR2dbcException; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.function.Function; import java.util.function.Supplier; @RestController @@ -21,7 +24,7 @@ public class ZipCodeApi { @GetMapping("/{zipcode}") public Mono findById(@PathVariable String zipcode) { - return zipRepo.findById(zipcode); + return getById(zipcode); } @GetMapping("/by_city") @@ -29,10 +32,23 @@ public class ZipCodeApi { return zipRepo.findByCity(city); } - @Transactional @PostMapping public Mono create(@RequestBody ZipCode zipCode) { - return zipRepo.findById(zipCode.getZip()).switchIfEmpty(Mono.defer(createZipCode(zipCode))); + return getById(zipCode.getZip()) + .switchIfEmpty(Mono.defer(createZipCode(zipCode))) + .onErrorResume(this::isKeyDuplicated, this.recoverWith(zipCode)); + } + + private Mono getById(String zipCode) { + return zipRepo.findById(zipCode); + } + + private boolean isKeyDuplicated(Throwable ex) { + return ex instanceof DataIntegrityViolationException || ex instanceof UncategorizedR2dbcException; + } + + private Function> recoverWith(ZipCode zipCode) { + return throwable -> zipRepo.findById(zipCode.getZip()); } private Supplier> createZipCode(ZipCode zipCode) { diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/resources/application.properties b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/resources/application.properties index 1d49b67fda..e303baf6f6 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/resources/application.properties +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/src/main/resources/application.properties @@ -1,5 +1,7 @@ -spring.r2dbc.url=${DB_URL:r2dbc:postgresql://localhost:5432/postgres} -spring.r2dbc.username=postgres -spring.r2dbc.password=example -spring.r2dbc.pool.enabled=true -spring.r2dbc.pool.maxSize=20 \ No newline at end of file +spring.r2dbc.url=${DB_URL:r2dbc:mysql://localhost:3306/baeldung?useSSL=true&requireSSL=true} +spring.r2dbc.properties.sslMode=required +spring.r2dbc.username=root +spring.r2dbc.password=root +spring.r2dbc.pool.enabled=true +spring.r2dbc.pool.maxSize=95 + diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/src/test/java/com/baeldung/spring_project/StartupIT.java b/quarkus-modules/quarkus-vs-springboot/spring-project/src/test/java/com/baeldung/spring_project/StartupIT.java index 7487e5aa7f..7715fdc1d2 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/src/test/java/com/baeldung/spring_project/StartupIT.java +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/src/test/java/com/baeldung/spring_project/StartupIT.java @@ -1,9 +1,20 @@ package com.baeldung.spring_project; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.boot.test.context.SpringBootTest; +import org.testcontainers.junit.jupiter.Testcontainers; -@SpringBootTest +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; + +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { "spring.r2dbc.url=r2dbc:tc:mysql:///baeldung?TC_IMAGE_TAG=5.7.34"} +) +@TestInstance(value = PER_CLASS) +@Testcontainers +@Disabled class StartupIT { @Test diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/cities.csv b/quarkus-modules/quarkus-vs-springboot/wrk/cities.csv new file mode 100644 index 0000000000..3b7016f3b5 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/cities.csv @@ -0,0 +1,136 @@ +Holtsville +Adjuntas +Aguada +Aguadilla +Maricao +Anasco +Angeles +Arecibo +Bajadero +Barceloneta +Boqueron +Cabo Rojo +Penuelas +Camuy +Castaner +Rosario +Sabana Grande +Ciales +Utuado +Dorado +Ensenada +Florida +Garrochales +Guanica +Guayanilla +Hatillo +Hormigueros +Isabela +Jayuya +Lajas +Lares +Las Marias +Manati +Moca +Rincon +Quebradillas +Mayaguez +San German +San Sebastian +Morovis +Sabana Hoyos +San Antonio +Vega Alta +Vega Baja +Yauco +Aguas Buenas +Aguirre +Aibonito +Maunabo +Arroyo +Mercedita +Ponce +Naguabo +Naranjito +Orocovis +Palmer +Patillas +Caguas +Canovanas +Ceiba +Cayey +Fajardo +Cidra +Puerto Real +Punta Santiago +Roosevelt Roads +Rio Blanco +Rio Grande +Salinas +San Lorenzo +Santa Isabel +Vieques +Villalba +Yabucoa +Coamo +Las Piedras +Loiza +Luquillo +Culebra +Juncos +Gurabo +Coto Laurel +Comerio +Corozal +Guayama +La Plata +Humacao +Barranquitas +Juana Diaz +St Thomas +Christiansted +St John +Frederiksted +Kingshill +San Juan +Fort Buchanan +Toa Baja +Sabana Seca +Toa Alta +Bayamon +Catano +Guaynabo +Trujillo Alto +Saint Just +Carolina +Agawam +Amherst +Barre +Belchertown +Blandford +Bondsville +Brimfield +Chester +Chesterfield +Chicopee +Cummington +Easthampton +East Longmeadow +East Otis +Feeding Hills +Gilbertville +Goshen +Granby +Granville +Hadley +Hampden +Hardwick +Hatfield +Haydenville +Holyoke +Huntington +Leeds +Leverett +Ludlow +Monson +North Amherst \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/generator.lua b/quarkus-modules/quarkus-vs-springboot/wrk/generator.lua new file mode 100644 index 0000000000..a1973072d9 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/generator.lua @@ -0,0 +1,65 @@ +local require = require +local json = require "json" + +math.randomseed(os.time()) + +-- read csv lines +function ParseCSVLine(line,sep) + local res = {} + local pos = 1 + sep = sep or ',' + while true do + local c = string.sub(line,pos,pos) + if (c == "") then break end + if (c == '"') then + local txt = "" + repeat + local startp,endp = string.find(line,'^%b""',pos) + txt = txt..string.sub(line,startp+1,endp-1) + pos = endp + 1 + c = string.sub(line,pos,pos) + if (c == '"') then txt = txt..'"' end + until (c ~= '"') + table.insert(res,txt) + assert(c == sep or c == "") + pos = pos + 1 + else + local startp,endp = string.find(line,sep,pos) + if (startp) then + table.insert(res,string.sub(line,pos,startp-1)) + pos = endp + 1 + else + table.insert(res,string.sub(line,pos)) + break + end + end + end + return res +end + +loadFile = function() + local filename = "zip_code_database.csv" + + local data = {} + local count = 0 + local sep = "," + + for line in io.lines(filename) do + local values = ParseCSVLine(line,sep) + data[count + 1] = { zip=values[1], type=values[2], city=values[4], state=values[7], county=values[8], timezone=values[9] } + count = count + 1 + end + + return data +end + +generator = function() + local data = loadFile() + return coroutine.create(function() + for k,v in pairs(data) do + coroutine.yield(json.stringify(v)) + end + end) +end + +return generator() \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/get_by_city.lua b/quarkus-modules/quarkus-vs-springboot/wrk/get_by_city.lua new file mode 100644 index 0000000000..b101e3bbda --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/get_by_city.lua @@ -0,0 +1,79 @@ +local require = require +local json = require "json" + +math.randomseed(os.clock()*100000000000) + +function ParseCSVLine(line,sep) + local res = {} + local pos = 1 + sep = sep or ',' + while true do + local c = string.sub(line,pos,pos) + if (c == "") then break end + if (c == '"') then + local txt = "" + repeat + local startp,endp = string.find(line,'^%b""',pos) + txt = txt..string.sub(line,startp+1,endp-1) + pos = endp + 1 + c = string.sub(line,pos,pos) + if (c == '"') then txt = txt..'"' end + until (c ~= '"') + table.insert(res,txt) + assert(c == sep or c == "") + pos = pos + 1 + else + local startp,endp = string.find(line,sep,pos) + if (startp) then + table.insert(res,string.sub(line,pos,startp-1)) + pos = endp + 1 + else + table.insert(res,string.sub(line,pos)) + break + end + end + end + return res +end + +loadFile = function() + local filename = "cities.csv" + + local data = {} + local count = 0 + local sep = "," + + for line in io.lines(filename) do + local values = ParseCSVLine(line,sep) + data[count + 1] = values[1] + count = count + 1 + end + + return data +end + +local data = loadFile() + +local urlencode = function (str) + str = string.gsub (str, "([^0-9a-zA-Z !'()*._~-])", -- locale independent + function (c) return string.format ("%%%02X", string.byte(c)) end) + str = string.gsub (str, " ", "+") + return str +end + +request = function() + url_path = "/zipcode/by_city?city=" .. urlencode(data[math.random(1, 136)]) + + local headers = { ["Content-Type"] = "application/json;charset=UTF-8" } + + return wrk.format("GET", url_path, headers, nil) +end + +done = function(summary, latency, requests) + io.write("--------------GET CITY ZIPCODES----------------\n") + for _, p in pairs({ 50, 90, 99, 99.999 }) do + n = latency:percentile(p) + io.write(string.format("%g%%,%d\n", p, n)) + end + io.write("-----------------------------------------------\n\n") +end \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/get_zipcode.lua b/quarkus-modules/quarkus-vs-springboot/wrk/get_zipcode.lua new file mode 100644 index 0000000000..f2abf607c2 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/get_zipcode.lua @@ -0,0 +1,77 @@ +local require = require +local json = require "json" + +math.randomseed(os.clock()*100000000000) + +function ParseCSVLine(line,sep) + local res = {} + local pos = 1 + sep = sep or ',' + while true do + local c = string.sub(line,pos,pos) + if (c == "") then break end + if (c == '"') then + local txt = "" + repeat + local startp,endp = string.find(line,'^%b""',pos) + txt = txt..string.sub(line,startp+1,endp-1) + pos = endp + 1 + c = string.sub(line,pos,pos) + if (c == '"') then txt = txt..'"' end + + until (c ~= '"') + table.insert(res,txt) + assert(c == sep or c == "") + pos = pos + 1 + else + local startp,endp = string.find(line,sep,pos) + if (startp) then + table.insert(res,string.sub(line,pos,startp-1)) + pos = endp + 1 + else + table.insert(res,string.sub(line,pos)) + break + end + end + end + return res +end + +loadFile = function() + local filename = "zip_code_database.csv" + + local data = {} + local count = 0 + local sep = "," + + for line in io.lines(filename) do + local values = ParseCSVLine(line,sep) + data[count + 1] = values[1] + count = count + 1 + end + + return data +end + +local data = loadFile() + +request = function() + + local value = data[math.random(1, 12079)] + + url_path = "/zipcode/" .. value + + local headers = { ["Content-Type"] = "application/json;charset=UTF-8" } + + return wrk.format("GET", url_path, headers, nil) +end + + +done = function(summary, latency, requests) + io.write("--------------GET ZIPCODE----------------\n") + for _, p in pairs({ 50, 90, 99, 99.999 }) do + n = latency:percentile(p) + io.write(string.format("%g%%,%d\n", p, n)) + end + io.write("-----------------------------------------\n\n") +end diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/json.lua b/quarkus-modules/quarkus-vs-springboot/wrk/json.lua new file mode 100644 index 0000000000..6f023a9294 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/json.lua @@ -0,0 +1,133 @@ +local json = {} + +local function kind_of(obj) + if type(obj) ~= 'table' then return type(obj) end + local i = 1 + for _ in pairs(obj) do + if obj[i] ~= nil then i = i + 1 else return 'table' end + end + if i == 1 then return 'table' else return 'array' end +end + +local function escape_str(s) + local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'} + local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'} + for i, c in ipairs(in_char) do + s = s:gsub(c, '\\' .. out_char[i]) + end + return s +end + +local function skip_delim(str, pos, delim, err_if_missing) + pos = pos + #str:match('^%s*', pos) + if str:sub(pos, pos) ~= delim then + if err_if_missing then + error('Expected ' .. delim .. ' near position ' .. pos) + end + return pos, false + end + return pos + 1, true +end + +local function parse_str_val(str, pos, val) + val = val or '' + local early_end_error = 'End of input found while parsing string.' + if pos > #str then error(early_end_error) end + local c = str:sub(pos, pos) + if c == '"' then return val, pos + 1 end + if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end + local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'} + local nextc = str:sub(pos + 1, pos + 1) + if not nextc then error(early_end_error) end + return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc)) +end + +local function parse_num_val(str, pos) + local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos) + local val = tonumber(num_str) + if not val then error('Error parsing number at position ' .. pos .. '.') end + return val, pos + #num_str +end + +function json.stringify(obj, as_key) + local s = {} + local kind = kind_of(obj) + if kind == 'array' then + if as_key then error('Can\'t encode array as key.') end + s[#s + 1] = '[' + for i, val in ipairs(obj) do + if i > 1 then s[#s + 1] = ', ' end + s[#s + 1] = json.stringify(val) + end + s[#s + 1] = ']' + elseif kind == 'table' then + if as_key then error('Can\'t encode table as key.') end + s[#s + 1] = '{' + for k, v in pairs(obj) do + if #s > 1 then s[#s + 1] = ', ' end + s[#s + 1] = json.stringify(k, true) + s[#s + 1] = ':' + s[#s + 1] = json.stringify(v) + end + s[#s + 1] = '}' + elseif kind == 'string' then + return '"' .. escape_str(obj) .. '"' + elseif kind == 'number' then + if as_key then return '"' .. tostring(obj) .. '"' end + return tostring(obj) + elseif kind == 'boolean' then + return tostring(obj) + elseif kind == 'nil' then + return 'null' + else + error('Unjsonifiable type: ' .. kind .. '.') + end + return table.concat(s) +end + +json.null = {} + +function json.parse(str, pos, end_delim) + pos = pos or 1 + if pos > #str then error('Reached unexpected end of input.') end + local pos = pos + #str:match('^%s*', pos) + local first = str:sub(pos, pos) + if first == '{' then + local obj, key, delim_found = {}, true, true + pos = pos + 1 + while true do + key, pos = json.parse(str, pos, '}') + if key == nil then return obj, pos end + if not delim_found then error('Comma missing between object items.') end + pos = skip_delim(str, pos, ':', true) + obj[key], pos = json.parse(str, pos) + pos, delim_found = skip_delim(str, pos, ',') + end + elseif first == '[' then + local arr, val, delim_found = {}, true, true + pos = pos + 1 + while true do + val, pos = json.parse(str, pos, ']') + if val == nil then return arr, pos end + if not delim_found then error('Comma missing between array items.') end + arr[#arr + 1] = val + pos, delim_found = skip_delim(str, pos, ',') + end + elseif first == '"' then + return parse_str_val(str, pos + 1) + elseif first == '-' or first:match('%d') then + return parse_num_val(str, pos) + elseif first == end_delim then + return nil, pos + 1 + else + local literals = {['true'] = true, ['false'] = false, ['null'] = json.null} + for lit_str, lit_val in pairs(literals) do + local lit_end = pos + #lit_str - 1 + if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end + end + local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10) + error('Invalid json syntax starting at ' .. pos_info_str) + end +end + +return json diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/post_zipcode.lua b/quarkus-modules/quarkus-vs-springboot/wrk/post_zipcode.lua new file mode 100644 index 0000000000..b8e60da015 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/post_zipcode.lua @@ -0,0 +1,73 @@ +local require = require +local json = require "json" + +math.randomseed(os.clock()*100000000000) + +function ParseCSVLine(line,sep) + local res = {} + local pos = 1 + sep = sep or ',' + while true do + local c = string.sub(line,pos,pos) + if (c == "") then break end + if (c == '"') then + local txt = "" + repeat + local startp,endp = string.find(line,'^%b""',pos) + txt = txt..string.sub(line,startp+1,endp-1) + pos = endp + 1 + c = string.sub(line,pos,pos) + if (c == '"') then txt = txt..'"' end + + until (c ~= '"') + table.insert(res,txt) + assert(c == sep or c == "") + pos = pos + 1 + else + local startp,endp = string.find(line,sep,pos) + if (startp) then + table.insert(res,string.sub(line,pos,startp-1)) + pos = endp + 1 + else + table.insert(res,string.sub(line,pos)) + break + end + end + end + return res +end + +loadFile = function() + local filename = "zip_code_database.csv" + + local data = {} + local count = 0 + local sep = "," + + for line in io.lines(filename) do + local values = ParseCSVLine(line,sep) + data[count + 1] = { zip=values[1], type=values[2], city=values[4], state=values[7], county=values[8], timezone=values[9] } + count = count + 1 + end + + return data +end + +local data = loadFile() + +request = function() + local url_path = "/zipcode" + local val = data[math.random(1, 12079)] + + local headers = { ["Content-Type"] = "application/json;charset=UTF-8" } + return wrk.format("POST", url_path, headers, json.stringify(val)) +end + +done = function(summary, latency, requests) + io.write("--------------POST ZIPCODE----------------\n") + for _, p in pairs({ 50, 75, 90, 99, 99.999 }) do + n = latency:percentile(p) + io.write(string.format("%g%%,%d\n", p, n)) + end + io.write("------------------------------------------\n\n") +end \ No newline at end of file diff --git a/quarkus-modules/quarkus-vs-springboot/wrk/run_test_wrk.sh b/quarkus-modules/quarkus-vs-springboot/wrk/run_test_wrk.sh new file mode 100755 index 0000000000..0d565d0688 --- /dev/null +++ b/quarkus-modules/quarkus-vs-springboot/wrk/run_test_wrk.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +$wrk_home/wrk -t1 -c5 -d1m -s ./post_zipcode.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 & sleep 60 + +$wrk_home/wrk -t1 -c20 -d5m -s ./post_zipcode.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 & sleep 60 + +$wrk_home/wrk -t1 -c20 -d5m -s ./get_by_city.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 \ & +$wrk_home/wrk -t1 -c20 -d5m -s ./get_zipcode.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 \ & sleep 120 + +$wrk_home/wrk -t2 -c10 -d3m -s ./get_by_city.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 \ & +$wrk_home/wrk -t2 -c10 -d3m -s ./get_zipcode.lua --timeout 2m -H 'Host: localhost' http://localhost:8080 \ & + +wait + From 858e15868027f4a975527965a58b6a7ac34a49e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matei=20Cern=C4=83ianu?= <34006140+matei-cernaianu@users.noreply.github.com> Date: Sun, 31 Jul 2022 02:18:52 +0300 Subject: [PATCH 20/39] BAEL-5651: How to check if an integer is in a given range? (#12470) * BAEL-5651: How to check if an integer is in a given range? * BAEL-5651: How to check if an integer is in a given range? --- core-java-modules/core-java-numbers-5/pom.xml | 18 ++++ .../intrange/IntRangeApacheCommons.java | 26 +++++ .../intrange/IntRangeGoogleGuava.java | 26 +++++ .../baeldung/intrange/IntRangeOperators.java | 20 ++++ .../baeldung/intrange/IntRangeValueRange.java | 26 +++++ .../IntRangeApacheCommonsUnitTest.java | 97 +++++++++++++++++++ .../intrange/IntRangeGoogleGuavaUnitTest.java | 87 +++++++++++++++++ .../intrange/IntRangeOperatorsUnitTest.java | 87 +++++++++++++++++ .../intrange/IntRangeValueRangeUnitTest.java | 97 +++++++++++++++++++ 9 files changed, 484 insertions(+) create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeApacheCommons.java create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeGoogleGuava.java create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeOperators.java create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeValueRange.java create mode 100644 core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeApacheCommonsUnitTest.java create mode 100644 core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeGoogleGuavaUnitTest.java create mode 100644 core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeOperatorsUnitTest.java create mode 100644 core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeValueRangeUnitTest.java diff --git a/core-java-modules/core-java-numbers-5/pom.xml b/core-java-modules/core-java-numbers-5/pom.xml index f236d28ccb..bab1e4d622 100644 --- a/core-java-modules/core-java-numbers-5/pom.xml +++ b/core-java-modules/core-java-numbers-5/pom.xml @@ -22,4 +22,22 @@ + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + com.google.guava + guava + ${guava.version} + + \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeApacheCommons.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeApacheCommons.java new file mode 100644 index 0000000000..0a82f934a7 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeApacheCommons.java @@ -0,0 +1,26 @@ +package com.baeldung.intrange; + +import org.apache.commons.lang3.Range; + +public class IntRangeApacheCommons { + + public static boolean isInClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.between(lowerBound, upperBound); + return range.contains(number); + } + + public static boolean isInOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.between(lowerBound + 1, upperBound - 1); + return range.contains(number); + } + + public static boolean isInOpenClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.between(lowerBound + 1, upperBound); + return range.contains(number); + } + + public static boolean isInClosedOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.between(lowerBound, upperBound - 1); + return range.contains(number); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeGoogleGuava.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeGoogleGuava.java new file mode 100644 index 0000000000..d4cadfa050 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeGoogleGuava.java @@ -0,0 +1,26 @@ +package com.baeldung.intrange; + +import com.google.common.collect.Range; + +public class IntRangeGoogleGuava { + + public static boolean isInClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.closed(lowerBound, upperBound); + return range.contains(number); + } + + public static boolean isInOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.open(lowerBound, upperBound); + return range.contains(number); + } + + public static boolean isInOpenClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.openClosed(lowerBound, upperBound); + return range.contains(number); + } + + public static boolean isInClosedOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final Range range = Range.closedOpen(lowerBound, upperBound); + return range.contains(number); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeOperators.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeOperators.java new file mode 100644 index 0000000000..77e32161e0 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeOperators.java @@ -0,0 +1,20 @@ +package com.baeldung.intrange; + +public class IntRangeOperators { + + public static boolean isInClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + return (lowerBound <= number && number <= upperBound); + } + + public static boolean isInOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + return (lowerBound < number && number < upperBound); + } + + public static boolean isInOpenClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + return (lowerBound < number && number <= upperBound); + } + + public static boolean isInClosedOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + return (lowerBound <= number && number < upperBound); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeValueRange.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeValueRange.java new file mode 100644 index 0000000000..cdce555341 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/intrange/IntRangeValueRange.java @@ -0,0 +1,26 @@ +package com.baeldung.intrange; + +import java.time.temporal.ValueRange; + +public class IntRangeValueRange { + + public static boolean isInClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final ValueRange range = ValueRange.of(lowerBound, upperBound); + return range.isValidIntValue(number); + } + + public static boolean isInOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final ValueRange range = ValueRange.of(lowerBound + 1, upperBound - 1); + return range.isValidIntValue(number); + } + + public static boolean isInOpenClosedRange(Integer number, Integer lowerBound, Integer upperBound) { + final ValueRange range = ValueRange.of(lowerBound + 1, upperBound); + return range.isValidIntValue(number); + } + + public static boolean isInClosedOpenRange(Integer number, Integer lowerBound, Integer upperBound) { + final ValueRange range = ValueRange.of(lowerBound, upperBound - 1); + return range.isValidIntValue(number); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeApacheCommonsUnitTest.java b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeApacheCommonsUnitTest.java new file mode 100644 index 0000000000..d3b15d0e42 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeApacheCommonsUnitTest.java @@ -0,0 +1,97 @@ +package com.baeldung.intrange; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class IntRangeApacheCommonsUnitTest { + + @Test + void givenIntRangeApacheCommons_whenIsInClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInClosedRange(10, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInClosedRange(20, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsNotInClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInClosedRange(8, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInClosedRange(22, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsInOpenRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInOpenRange(11, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInOpenRange(19, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsNotInOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsInOpenClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInOpenClosedRange(11, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInOpenClosedRange(20, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsNotInOpenClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInOpenClosedRange(10, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInOpenClosedRange(21, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsInClosedOpenRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInClosedOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInClosedOpenRange(19, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeApacheCommons_whenIsNotInClosedOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeApacheCommons.isInClosedOpenRange(9, 10, 20); + boolean resultUpperBound = IntRangeApacheCommons.isInClosedOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeGoogleGuavaUnitTest.java b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeGoogleGuavaUnitTest.java new file mode 100644 index 0000000000..9abdc20d31 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeGoogleGuavaUnitTest.java @@ -0,0 +1,87 @@ +package com.baeldung.intrange; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class IntRangeGoogleGuavaUnitTest { + + @Test + void givenIntRangeGoogleGuava_whenIsInOpenRange_thenSuccess() { + // when + boolean result = IntRangeGoogleGuava.isInOpenRange(14, 10, 20); + + //then + assertTrue(result); + } + + @Test + void givenIntRangeGoogleGuava_whenIsNotInOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeGoogleGuava.isInOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeGoogleGuava.isInOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeGoogleGuava_whenIsInClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeGoogleGuava.isInClosedRange(-10, -10, 5); + boolean resultUpperBound = IntRangeGoogleGuava.isInClosedRange(5, -10, 5); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeGoogleGuava_whenIsNotInClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeGoogleGuava.isInClosedRange(-11, -10, 5); + boolean resultUpperBound = IntRangeGoogleGuava.isInClosedRange(6, -10, 5); + + //then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeGoogleGuava_whenIsInOpenClosedRange_thenSuccess() { + // when + boolean result = IntRangeGoogleGuava.isInOpenClosedRange(20, 10, 20); + + // then + assertTrue(result); + } + + @Test + void givenIntRangeGoogleGuava_whenIsNotInOpenClosedRange_thenFailure() { + // when + boolean result = IntRangeGoogleGuava.isInOpenClosedRange(10, 10, 20); + + // then + assertFalse(result); + } + + @Test + void givenIntRangeGoogleGuava_whenIsInClosedOpenRange_thenSuccess() { + // when + boolean result = IntRangeGoogleGuava.isInClosedOpenRange(10, 10, 20); + + // then + assertTrue(result); + } + + @Test + void givenIntRangeGoogleGuava_whenIsNotInClosedOpenRange_thenFailure() { + // when + boolean result = IntRangeGoogleGuava.isInClosedOpenRange(20, 10, 20); + + // then + assertFalse(result); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeOperatorsUnitTest.java b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeOperatorsUnitTest.java new file mode 100644 index 0000000000..76abeb1ee3 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeOperatorsUnitTest.java @@ -0,0 +1,87 @@ +package com.baeldung.intrange; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class IntRangeOperatorsUnitTest { + + @Test + void givenIntRangeOperators_whenIsInOpenRange_thenSuccess() { + // when + boolean result = IntRangeOperators.isInOpenRange(11, 10, 20); + + //then + assertTrue(result); + } + + @Test + void givenIntRangeOperators_whenIsNotInOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeOperators.isInOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeOperators.isInOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeOperators_whenIsInClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeOperators.isInClosedRange(-10, -10, 5); + boolean resultUpperBound = IntRangeOperators.isInClosedRange(5, -10, 5); + + // then + assertTrue(resultUpperBound); + assertTrue(resultLowerBound); + } + + @Test + void givenIntRangeOperators_whenIsNotInClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeOperators.isInClosedRange(-11, -10, 5); + boolean resultUpperBound = IntRangeOperators.isInClosedRange(6, -10, 5); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeOperators_whenIsInOpenClosedRange_thenSuccess() { + // when + boolean result = IntRangeOperators.isInOpenClosedRange(20, 10, 20); + + // then + assertTrue(result); + } + + @Test + void givenIntRangeOperators_whenIsNotInOpenClosedRange_thenFailure() { + // when + boolean result = IntRangeOperators.isInOpenClosedRange(10, 10, 20); + + // then + assertFalse(result); + } + + @Test + void givenIntRangeOperators_whenIsInClosedOpenRange_thenSuccess() { + // when + boolean result = IntRangeOperators.isInClosedOpenRange(10, 10, 20); + + // then + assertTrue(result); + } + + @Test + void givenIntRangeOperators_whenIsNotInClosedOpenRange_thenFailure() { + // when + boolean result = IntRangeOperators.isInClosedOpenRange(20, 10, 20); + + // then + assertFalse(result); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeValueRangeUnitTest.java b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeValueRangeUnitTest.java new file mode 100644 index 0000000000..dc2105c675 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/intrange/IntRangeValueRangeUnitTest.java @@ -0,0 +1,97 @@ +package com.baeldung.intrange; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class IntRangeValueRangeUnitTest { + + @Test + void givenIntRangeValueRange_whenIsInClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeValueRange.isInClosedRange(10, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInClosedRange(20, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsNotInClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeValueRange.isInClosedRange(9, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInClosedRange(21, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsInOpenRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeValueRange.isInOpenRange(11, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInOpenRange(19, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsNotInOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeValueRange.isInOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsInOpenClosedRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeValueRange.isInOpenClosedRange(11, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInOpenClosedRange(20, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsNotInOpenClosedRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeValueRange.isInOpenClosedRange(10, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInOpenClosedRange(21, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsInClosedOpenRange_thenSuccess() { + // when + boolean resultLowerBound = IntRangeValueRange.isInClosedOpenRange(10, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInClosedOpenRange(19, 10, 20); + + // then + assertTrue(resultLowerBound); + assertTrue(resultUpperBound); + } + + @Test + void givenIntRangeValueRange_whenIsNotInClosedOpenRange_thenFailure() { + // when + boolean resultLowerBound = IntRangeValueRange.isInClosedOpenRange(9, 10, 20); + boolean resultUpperBound = IntRangeValueRange.isInClosedOpenRange(20, 10, 20); + + // then + assertFalse(resultLowerBound); + assertFalse(resultUpperBound); + } +} From 0ec6a036ba38122a9d092fe6f9de0db4eb4a189a Mon Sep 17 00:00:00 2001 From: lucaCambi77 Date: Sun, 31 Jul 2022 04:43:09 +0200 Subject: [PATCH 21/39] Spring Security: Upgrading the deprecated WebSecurityConfigurerAdapter (#12540) * add SecurityFilterChain application in spring security web boot 4 * pmd violation * fix: pom description * remove unused code, format * make tests grouped logically * add missing case for user role * rename package to lower case --- spring-security-modules/pom.xml | 1 + .../spring-security-web-boot-4/README.md | 10 ++ .../spring-security-web-boot-4/pom.xml | 39 ++++++++ .../SecurityFilterChainApplication.java | 14 +++ .../configuration/SecurityConfig.java | 50 ++++++++++ .../UserDetailServiceConfig.java | 31 ++++++ .../controller/ResourceController.java | 34 +++++++ .../SecurityFilterChainIntegrationTest.java | 94 +++++++++++++++++++ .../src/test/resources/application.properties | 1 + .../src/test/resources/logback-test.xml | 12 +++ 10 files changed, 286 insertions(+) create mode 100644 spring-security-modules/spring-security-web-boot-4/README.md create mode 100644 spring-security-modules/spring-security-web-boot-4/pom.xml create mode 100644 spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/SecurityFilterChainApplication.java create mode 100644 spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/SecurityConfig.java create mode 100644 spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/UserDetailServiceConfig.java create mode 100644 spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/controller/ResourceController.java create mode 100644 spring-security-modules/spring-security-web-boot-4/src/test/java/com/baeldung/securityfilterchain/SecurityFilterChainIntegrationTest.java create mode 100644 spring-security-modules/spring-security-web-boot-4/src/test/resources/application.properties create mode 100644 spring-security-modules/spring-security-web-boot-4/src/test/resources/logback-test.xml diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index 2bd6d23058..83412d2252 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -32,6 +32,7 @@ spring-security-web-boot-1 spring-security-web-boot-2 spring-security-web-boot-3 + spring-security-web-boot-4 spring-security-web-digest-auth spring-security-web-login spring-security-web-login-2 diff --git a/spring-security-modules/spring-security-web-boot-4/README.md b/spring-security-modules/spring-security-web-boot-4/README.md new file mode 100644 index 0000000000..0856315682 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/README.md @@ -0,0 +1,10 @@ +## Spring Boot Security MVC + +This module contains articles about Spring Security with Spring MVC in Boot applications + +### The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com + +### Relevant Articles: + +- More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-3) diff --git a/spring-security-modules/spring-security-web-boot-4/pom.xml b/spring-security-modules/spring-security-web-boot-4/pom.xml new file mode 100644 index 0000000000..8dd56e1de2 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + spring-security-web-boot-4 + 0.0.1-SNAPSHOT + spring-security-web-boot-4 + jar + Spring Security MVC Boot - 4 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/SecurityFilterChainApplication.java b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/SecurityFilterChainApplication.java new file mode 100644 index 0000000000..86f98b651b --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/SecurityFilterChainApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.securityfilterchain; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +@SpringBootApplication +@EnableWebMvc +public class SecurityFilterChainApplication { + + public static void main(String[] args) { + SpringApplication.run(SecurityFilterChainApplication.class, args); + } +} diff --git a/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/SecurityConfig.java b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/SecurityConfig.java new file mode 100644 index 0000000000..4d3bec2ad2 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/SecurityConfig.java @@ -0,0 +1,50 @@ +package com.baeldung.securityfilterchain.configuration; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; + +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) +public class SecurityConfig { + + @Value("${spring.security.debug:false}") + boolean securityDebug; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.csrf() + .disable() + .authorizeRequests() + .antMatchers(HttpMethod.DELETE) + .hasRole("ADMIN") + .antMatchers("/admin/**") + .hasAnyRole("ADMIN") + .antMatchers("/user/**") + .hasAnyRole("USER", "ADMIN") + .antMatchers("/login/**") + .anonymous() + .anyRequest() + .authenticated() + .and() + .httpBasic() + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + return http.build(); + } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.debug(securityDebug) + .ignoring() + .antMatchers("/css/**", "/js/**", "/img/**", "/lib/**", "/favicon.ico"); + } +} diff --git a/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/UserDetailServiceConfig.java b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/UserDetailServiceConfig.java new file mode 100644 index 0000000000..6a614e888b --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/configuration/UserDetailServiceConfig.java @@ -0,0 +1,31 @@ +package com.baeldung.securityfilterchain.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +public class UserDetailServiceConfig { + + @Bean + public UserDetailsService userDetailsService(BCryptPasswordEncoder bCryptPasswordEncoder) { + InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); + manager.createUser(User.withUsername("user") + .password(bCryptPasswordEncoder.encode("userPass")) + .roles("USER") + .build()); + manager.createUser(User.withUsername("admin") + .password(bCryptPasswordEncoder.encode("adminPass")) + .roles("ADMIN", "USER") + .build()); + return manager; + } + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/controller/ResourceController.java b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/controller/ResourceController.java new file mode 100644 index 0000000000..e01d4ae9b3 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/main/java/com/baeldung/securityfilterchain/controller/ResourceController.java @@ -0,0 +1,34 @@ +package com.baeldung.securityfilterchain.controller; + +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ResourceController { + @GetMapping("/login") + public String loginEndpoint() { + return "Login!"; + } + + @GetMapping("/admin") + public String adminEndpoint() { + return "Admin!"; + } + + @GetMapping("/user") + public String userEndpoint() { + return "User!"; + } + + @GetMapping("/all") + public String allRolesEndpoint() { + return "All Roles!"; + } + + @DeleteMapping("/delete") + public String deleteEndpoint(@RequestBody String s) { + return "I am deleting " + s; + } +} diff --git a/spring-security-modules/spring-security-web-boot-4/src/test/java/com/baeldung/securityfilterchain/SecurityFilterChainIntegrationTest.java b/spring-security-modules/spring-security-web-boot-4/src/test/java/com/baeldung/securityfilterchain/SecurityFilterChainIntegrationTest.java new file mode 100644 index 0000000000..e94b1b2f12 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/test/java/com/baeldung/securityfilterchain/SecurityFilterChainIntegrationTest.java @@ -0,0 +1,94 @@ +package com.baeldung.securityfilterchain; + +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +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.security.test.context.support.WithAnonymousUser; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest(classes = SecurityFilterChainApplication.class) +public class SecurityFilterChainIntegrationTest { + @Autowired + private WebApplicationContext context; + + private MockMvc mvc; + + @BeforeEach + public void setup() { + mvc = MockMvcBuilders.webAppContextSetup(context) + .apply(springSecurity()) + .build(); + } + + @Test + @WithUserDetails(value = "admin") + public void whenAdminAccessUserEndpoint_thenOk() throws Exception { + mvc.perform(get("/user")) + .andExpect(status().isOk()); + } + + @Test + @WithUserDetails(value = "admin") + public void whenAdminAccessAdminSecuredEndpoint_thenIsOk() throws Exception { + mvc.perform(get("/admin")) + .andExpect(status().isOk()); + } + + @Test + @WithUserDetails(value = "admin") + public void whenAdminAccessDeleteSecuredEndpoint_thenIsOk() throws Exception { + mvc.perform(delete("/delete").content("{}")) + .andExpect(status().isOk()); + } + + @Test + @WithAnonymousUser + public void whenAnonymousAccessLogin_thenOk() throws Exception { + mvc.perform(get("/login")) + .andExpect(status().isOk()); + } + + @Test + @WithAnonymousUser + public void whenAnonymousAccessRestrictedEndpoint_thenIsUnauthorized() throws Exception { + mvc.perform(get("/all")) + .andExpect(status().isUnauthorized()); + } + + @Test + @WithUserDetails() + public void whenUserAccessUserSecuredEndpoint_thenOk() throws Exception { + mvc.perform(get("/user")) + .andExpect(status().isOk()); + } + + @Test + @WithUserDetails() + public void whenUserAccessRestrictedEndpoint_thenOk() throws Exception { + mvc.perform(get("/all")) + .andExpect(status().isOk()); + } + + @Test + @WithUserDetails() + public void whenUserAccessAdminSecuredEndpoint_thenIsForbidden() throws Exception { + mvc.perform(get("/admin")) + .andExpect(status().isForbidden()); + } + + @Test + @WithUserDetails() + public void whenUserAccessDeleteSecuredEndpoint_thenIsForbidden() throws Exception { + mvc.perform(delete("/delete")) + .andExpect(status().isForbidden()); + } +} diff --git a/spring-security-modules/spring-security-web-boot-4/src/test/resources/application.properties b/spring-security-modules/spring-security-web-boot-4/src/test/resources/application.properties new file mode 100644 index 0000000000..090ff54e92 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.security.debug=true \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-4/src/test/resources/logback-test.xml b/spring-security-modules/spring-security-web-boot-4/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..c5a4b0ab1c --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-4/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file From ac46a475248282689bdbc81b8b2e9ce215e43342 Mon Sep 17 00:00:00 2001 From: "thibault.faure" Date: Sun, 24 Jul 2022 17:12:14 +0200 Subject: [PATCH 22/39] BAEL-5664 code for the using environment varibales in application.properties article --- spring-core-6/pom.xml | 29 ++++++--- .../envvariables/BaeldungProperties.java | 20 +++++++ .../baeldung/envvariables/MyController.java | 60 +++++++++++++++++++ .../src/main/resources/application.properties | 4 ++ .../MyControllerIntegrationTest.java | 36 +++++++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 spring-core-6/src/main/java/com/baeldung/envvariables/BaeldungProperties.java create mode 100644 spring-core-6/src/main/java/com/baeldung/envvariables/MyController.java create mode 100644 spring-core-6/src/main/resources/application.properties create mode 100644 spring-core-6/src/test/java/com/baeldung/envvariables/MyControllerIntegrationTest.java diff --git a/spring-core-6/pom.xml b/spring-core-6/pom.xml index 92cd343234..af6fb50e1d 100644 --- a/spring-core-6/pom.xml +++ b/spring-core-6/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung @@ -10,23 +10,36 @@ spring-core-6 http://www.baeldung.com + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + UTF-8 11 11 + 2.7.2 - junit - junit - 4.11 - test + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} org.springframework.boot - spring-boot-starter-web - 2.0.0.RELEASE + spring-boot-starter-test + ${spring.boot.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test diff --git a/spring-core-6/src/main/java/com/baeldung/envvariables/BaeldungProperties.java b/spring-core-6/src/main/java/com/baeldung/envvariables/BaeldungProperties.java new file mode 100644 index 0000000000..a41ac7a509 --- /dev/null +++ b/spring-core-6/src/main/java/com/baeldung/envvariables/BaeldungProperties.java @@ -0,0 +1,20 @@ +package com.baeldung.envvariables.valueinjection; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "baeldung") +public class BaeldungProperties { + + private String presentation; + + public String getPresentation() { + return presentation; + } + + public void setPresentation(String presentation) { + this.presentation = presentation; + } + +} diff --git a/spring-core-6/src/main/java/com/baeldung/envvariables/MyController.java b/spring-core-6/src/main/java/com/baeldung/envvariables/MyController.java new file mode 100644 index 0000000000..503ee47157 --- /dev/null +++ b/spring-core-6/src/main/java/com/baeldung/envvariables/MyController.java @@ -0,0 +1,60 @@ +package com.baeldung.envvariables.valueinjection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MyController { + + @Value("${environment.name}") + private String environmentName; + + @Value("${java.home.and.environment}") + private String javaHomeAndEnvironmentName; + + @Value("${thispropertydoesnotexist}") + private String nonExistentProperty; + + @Value("${baeldung.presentation}") + private String baeldungPresentation; + + @Autowired + private Environment environment; + + @Autowired + private BaeldungProperties baeldungProperties; + + @GetMapping("/environment_name") + String getEnvironmentName_FromEnvironmentVariables() { + return environmentName; + } + + @GetMapping("/java_home_and_environment") + String getJavaHomeAndEnvironmentName_FromEnvironmentVariables() { + return javaHomeAndEnvironmentName; + } + + @GetMapping("non_existent_property") + String getNonexistentProperty_FromEnvironmentVariables() { + return nonExistentProperty; + } + + @GetMapping("baeldung_presentation_from_value") + String getBaeldungPresentation_FromValue() { + return baeldungPresentation; + } + + @GetMapping("baeldung_presentation_from_environment") + String getBaeldungPresentation_FromEnvironment() { + return environment.getProperty("baeldung.presentation"); + } + + @GetMapping("baeldung_configuration_properties") + String getBaeldungPresentation_FromConfigurationProperties() { + return baeldungProperties.getPresentation(); + } + +} diff --git a/spring-core-6/src/main/resources/application.properties b/spring-core-6/src/main/resources/application.properties new file mode 100644 index 0000000000..d0029f363c --- /dev/null +++ b/spring-core-6/src/main/resources/application.properties @@ -0,0 +1,4 @@ +environment.name=${OS} +java.home.and.environment=${JAVA_HOME}+${OS} +not.existing.system.property=${thispropertydoesnotexist} +baeldung.presentation=${HELLO_BAELDUNG}. Java is installed in the folder: ${JAVA_HOME} \ No newline at end of file diff --git a/spring-core-6/src/test/java/com/baeldung/envvariables/MyControllerIntegrationTest.java b/spring-core-6/src/test/java/com/baeldung/envvariables/MyControllerIntegrationTest.java new file mode 100644 index 0000000000..b3ee2c7c46 --- /dev/null +++ b/spring-core-6/src/test/java/com/baeldung/envvariables/MyControllerIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.envvariables.valueinjection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +@SpringBootTest(classes = MyController.class) +@AutoConfigureMockMvc +public class MyControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + /** NB : these tests are commented out because they are environment dependent + * If you want to run one of them on your machine, follow the instruction above it + * + * expects the value of your system environment property 'OS' (it is already defined at least in Windows_NT) + @Test void givenExistingSystemProperty_whenInjected_thenHasSystemPropertyValue() throws Exception { + mockMvc.perform(get("/environment_name")) + .andExpect(content().string(equalTo("Windows_NT"))); + } + + * expects the value of the JAVA_HOME environment variable (you need to define it if you haven't yet), with a + and the 'OS' environment property in the end + @Test void givenCombinationOfSystemPropertyAndEnvironmentVariable_whenInjected_thenHasExpectedValue() throws Exception { + mockMvc.perform(get("/java_home_and_environment")) + .andExpect(content().string(equalTo("C:\\Program Files\\Java\\jdk-11.0.14+Windows_NT"))); + } + + * expects the content to be ${thispropertydoesnotexist} ; if you have defined an environment property called thispropertydoesnotexist, it would fail + @Test void givenNonExistentProperty_whenInjected_thenKeepsTheStringValue() throws Exception { + mockMvc.perform(get("/non_existent_property")) + .andExpect(content().string(equalTo("${thispropertydoesnotexist}"))); + } + */ +} From 53629eeb0b980daaaa8c8045f0ac0878e3964214 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sun, 31 Jul 2022 21:57:45 +0530 Subject: [PATCH 23/39] JAVA-13627 Updated code to use assertThatThrownBy instead of assertThrows --- .../com/baeldung/mockito/MockitoMockUnitTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoMockUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoMockUnitTest.java index 80f01338e6..6b2bae16c3 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoMockUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/MockitoMockUnitTest.java @@ -2,7 +2,7 @@ package com.baeldung.mockito; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -33,11 +33,10 @@ public class MockitoMockUnitTest { MyList listMock = mock(MyList.class, "myMock"); when(listMock.add(anyString())).thenReturn(false); listMock.add(randomAlphabetic(6)); - - Throwable exceptionThrown = assertThrows(TooFewActualInvocations.class, - () -> verify(listMock, times(2)).add(anyString())); - - assertThat(exceptionThrown.getMessage()).contains("myMock.add"); + + assertThatThrownBy(() -> verify(listMock, times(2)).add(anyString())) + .isInstanceOf(TooFewActualInvocations.class) + .hasMessageContaining("myMock.add"); } private static class CustomAnswer implements Answer { From 614795051ef4263358e8f9aeeec8bde2aa99ea83 Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Tue, 2 Aug 2022 03:16:24 +0200 Subject: [PATCH 24/39] BAEL-5682 - Atomic vs Volatile (#12528) Co-authored-by: eugene.kovko --- .../atomicvsvolatile/SafeAtomicCounter.java | 16 ++++++++++++ .../atomicvsvolatile/UnsafeCounter.java | 14 +++++++++++ .../UnsafeVolatileCounter.java | 14 +++++++++++ .../SafeAtomicCounterUnitTest.java | 25 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/SafeAtomicCounter.java create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeCounter.java create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeVolatileCounter.java create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/atomicvsvolatile/SafeAtomicCounterUnitTest.java diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/SafeAtomicCounter.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/SafeAtomicCounter.java new file mode 100644 index 0000000000..196662e3ea --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/SafeAtomicCounter.java @@ -0,0 +1,16 @@ +package com.baeldung.atomicvsvolatile; + +import java.util.concurrent.atomic.AtomicInteger; + +public class SafeAtomicCounter { + + private final AtomicInteger counter = new AtomicInteger(0); + + public int getValue() { + return counter.get(); + } + + public void increment() { + counter.incrementAndGet(); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeCounter.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeCounter.java new file mode 100644 index 0000000000..48094672e1 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeCounter.java @@ -0,0 +1,14 @@ +package com.baeldung.atomicvsvolatile; + +public class UnsafeCounter { + + private int counter; + + public int getValue() { + return counter; + } + + public void increment() { + counter++; + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeVolatileCounter.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeVolatileCounter.java new file mode 100644 index 0000000000..6d06d5b12a --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/atomicvsvolatile/UnsafeVolatileCounter.java @@ -0,0 +1,14 @@ +package com.baeldung.atomicvsvolatile; + +public class UnsafeVolatileCounter { + + private volatile int counter; + + public int getValue() { + return counter; + } + + public void increment() { + counter++; + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/atomicvsvolatile/SafeAtomicCounterUnitTest.java b/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/atomicvsvolatile/SafeAtomicCounterUnitTest.java new file mode 100644 index 0000000000..4eb65db716 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/atomicvsvolatile/SafeAtomicCounterUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.atomicvsvolatile; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; +import org.junit.Test; + +public class SafeAtomicCounterUnitTest { + + private static final int INCREMENT_COUNTER = 1000; + private static final int TIMEOUT = 100; + private static final int POOL_SIZE = 3; + + @Test + public void givenMultiThread_whenSafeAtomicCounterIncrement() throws InterruptedException { + ExecutorService service = Executors.newFixedThreadPool(POOL_SIZE); + SafeAtomicCounter safeCounter = new SafeAtomicCounter(); + IntStream.range(0, INCREMENT_COUNTER).forEach(count -> service.submit(safeCounter::increment)); + service.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS); + assertEquals(INCREMENT_COUNTER, safeCounter.getValue()); + } +} \ No newline at end of file From a6ef4b67d112da05c2738191820264983f0a0b5b Mon Sep 17 00:00:00 2001 From: sdhiray7 Date: Wed, 3 Aug 2022 06:06:48 +0530 Subject: [PATCH 25/39] BAEL-5608 - Get current stack trace java (#12533) * Initial commit for Object copy in Java * review comments commit for Object copy in Java * Initial commit for parseInt vs valueOf java * Review comments commit for parseInt vs valueOf java * Modify readme * review comments * build failure * build failure retry * build failure retry remove parseInt(java.lang.String,int,int,int) * build failure add comment * change examples * review comments * review comments 2 * review comments 3 * Initial commit for get current stacktrace * Remove old files * Name updates * Jenkins error * changes to file name * Review comments --- .../currentstacktrace/DumpStackTraceDemo.java | 18 +++++++ .../StackTraceUsingThreadDemo.java | 16 ++++++ .../StackTraceUsingThrowableDemo.java | 21 ++++++++ .../CurrentStacktraceDemoUnitTest.java | 49 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/DumpStackTraceDemo.java create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThreadDemo.java create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThrowableDemo.java create mode 100644 core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/currentstacktrace/CurrentStacktraceDemoUnitTest.java diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/DumpStackTraceDemo.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/DumpStackTraceDemo.java new file mode 100644 index 0000000000..fb67814312 --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/DumpStackTraceDemo.java @@ -0,0 +1,18 @@ +package com.baeldung.exception.currentstacktrace; + +public class DumpStackTraceDemo +{ + public static void main(String[] args) { + methodA(); + } + + public static void methodA() { + try { + int num1 = 5/0; // java.lang.ArithmeticException: divide by zero + } + catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThreadDemo.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThreadDemo.java new file mode 100644 index 0000000000..a681fedd4f --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThreadDemo.java @@ -0,0 +1,16 @@ +package com.baeldung.exception.currentstacktrace; + +public class StackTraceUsingThreadDemo { + + public static void main(String[] args) { + methodA(); + } + + public static StackTraceElement[] methodA() { + return methodB(); + } + + public static StackTraceElement[] methodB() { + return Thread.currentThread().getStackTrace(); + } +} diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThrowableDemo.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThrowableDemo.java new file mode 100644 index 0000000000..fbc08596c6 --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/currentstacktrace/StackTraceUsingThrowableDemo.java @@ -0,0 +1,21 @@ +package com.baeldung.exception.currentstacktrace; + +public class StackTraceUsingThrowableDemo { + + public static void main(String[] args) { + methodA(); + } + + public static StackTraceElement[] methodA() { + try { + methodB(); + } catch (Throwable t) { + return t.getStackTrace(); + } + return null; + } + + public static void methodB() throws Throwable { + throw new Throwable("A test exception"); + } +} diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/currentstacktrace/CurrentStacktraceDemoUnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/currentstacktrace/CurrentStacktraceDemoUnitTest.java new file mode 100644 index 0000000000..849884204d --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/currentstacktrace/CurrentStacktraceDemoUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.exception.currentstacktrace; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.exception.currentstacktrace.StackTraceUsingThreadDemo; +import com.baeldung.exception.currentstacktrace.StackTraceUsingThrowableDemo; + +public class CurrentStacktraceDemoUnitTest { + + @Test + public void whenElementIsFecthedUsingThread_thenCorrectMethodAndClassIsReturned() { + StackTraceElement[] stackTrace = new StackTraceUsingThreadDemo().methodA(); + + StackTraceElement elementZero = stackTrace[0]; + assertEquals("java.lang.Thread", elementZero.getClassName()); + assertEquals("getStackTrace", elementZero.getMethodName()); + + StackTraceElement elementOne = stackTrace[1]; + assertEquals("com.baeldung.exception.currentstacktrace.StackTraceUsingThreadDemo", elementOne.getClassName()); + assertEquals("methodB", elementOne.getMethodName()); + + StackTraceElement elementTwo = stackTrace[2]; + assertEquals("com.baeldung.exception.currentstacktrace.StackTraceUsingThreadDemo", elementTwo.getClassName()); + assertEquals("methodA", elementTwo.getMethodName()); + + StackTraceElement elementThree = stackTrace[3]; + assertEquals("com.baeldung.exception.currentstacktrace.CurrentStacktraceDemoUnitTest", elementThree.getClassName()); + assertEquals("whenElementIsFecthedUsingThread_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName()); + } + + @Test + public void whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned() { + StackTraceElement[] stackTrace = new StackTraceUsingThrowableDemo().methodA(); + + StackTraceElement elementZero = stackTrace[0]; + assertEquals("com.baeldung.exception.currentstacktrace.StackTraceUsingThrowableDemo", elementZero.getClassName()); + assertEquals("methodB", elementZero.getMethodName()); + + StackTraceElement elementOne = stackTrace[1]; + assertEquals("com.baeldung.exception.currentstacktrace.StackTraceUsingThrowableDemo", elementOne.getClassName()); + assertEquals("methodA", elementOne.getMethodName()); + + StackTraceElement elementThree = stackTrace[2]; + assertEquals("com.baeldung.exception.currentstacktrace.CurrentStacktraceDemoUnitTest", elementThree.getClassName()); + assertEquals("whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName()); + } +} From 8ec8c01a6756e16901d3ff240a50b4349290bb8d Mon Sep 17 00:00:00 2001 From: Kai Yuan Date: Thu, 4 Aug 2022 04:38:13 +0200 Subject: [PATCH 26/39] Arrays.asList() vs Collections.singletonList() (#12552) --- .../ArraysAsListVsSingletonListUnitTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/aslistvssingletonlist/ArraysAsListVsSingletonListUnitTest.java diff --git a/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/aslistvssingletonlist/ArraysAsListVsSingletonListUnitTest.java b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/aslistvssingletonlist/ArraysAsListVsSingletonListUnitTest.java new file mode 100644 index 0000000000..b12693ab14 --- /dev/null +++ b/core-java-modules/core-java-collections-list-4/src/test/java/com/baeldung/list/aslistvssingletonlist/ArraysAsListVsSingletonListUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.list.aslistvssingletonlist; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +class ArraysAsListVsSingletonListUnitTest { + + @Test + void givenListFromArraysAsList_whenChangingStructureAndElement_thenGetExpectedResult() { + List arraysAsList = Arrays.asList("ONE"); + assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy( + () -> arraysAsList.add("TWO") + ); + + arraysAsList.set(0, "A brand new string"); + assertThat(arraysAsList.get(0)).isEqualTo("A brand new string"); + } + + @Test + void givenSingletonList_whenChangingStructureAndElement_thenThrowException() { + List singletonList = Collections.singletonList("ONE"); + assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy( + () -> singletonList.add("TWO") + ); + assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy( + () -> singletonList.set(0, "A brand new string") + ); + } + + @Test + void givenAnArray_whengetListByArraysAsList_thenTheListIsBackedByTheArray() { + String[] theArray = new String[] { "ONE", "TWO" }; + List theList = Arrays.asList(theArray); + //changing the list, the array is changed too + theList.set(0, "ONE [changed in list]"); + assertThat(theArray[0]).isEqualTo("ONE [changed in list]"); + + //changing the array, the list is changed too + theArray[1] = "TWO [changed in array]"; + assertThat(theList.get(1)).isEqualTo("TWO [changed in array]"); + } +} \ No newline at end of file From 81b05fb3ac49abeaa7defdfbf227462d86f78219 Mon Sep 17 00:00:00 2001 From: Adrian Bob Date: Thu, 4 Aug 2022 06:54:49 +0300 Subject: [PATCH 27/39] BAEL-5638: Added display logged-in user details in Thymeleaf tutorial (#12524) * BAEL-5638: Added display logged-in user details in Thymeleaf tutorial * BAEL-5638: Removed unneeded security config --- .../customuserdetails/CustomUserDetails.java | 94 +++++++++++++++++++ .../CustomUserDetailsService.java | 52 ++++++++++ .../PasswordEncoderConfiguration.java | 15 +++ .../SecurityConfiguration.java | 38 ++++++++ .../SpringSecurityThymeleafApplication.java | 12 +++ .../customuserdetails/ViewController.java | 21 +++++ .../main/resources/templates/userdetails.html | 25 +++++ ...tyThymeleafApplicationIntegrationTest.java | 29 ++++++ .../ViewControllerIntegrationTest.java | 42 +++++++++ 9 files changed, 328 insertions(+) create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetails.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetailsService.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/PasswordEncoderConfiguration.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SecurityConfiguration.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplication.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/ViewController.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/main/resources/templates/userdetails.html create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplicationIntegrationTest.java create mode 100644 spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/ViewControllerIntegrationTest.java diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetails.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetails.java new file mode 100644 index 0000000000..380d9d1092 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetails.java @@ -0,0 +1,94 @@ +package com.baeldung.customuserdetails; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.util.Collection; +import java.util.Objects; + +public class CustomUserDetails extends User { + + private final String firstName; + private final String lastName; + private final String email; + + private CustomUserDetails(Builder builder) { + super(builder.username, builder.password, builder.authorities); + this.firstName = builder.firstName; + this.lastName = builder.lastName; + this.email = builder.email; + } + + public String getLastName() { + return this.lastName; + } + + public String getFirstName() { + return this.firstName; + } + + public String getEmail() { + return email; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + CustomUserDetails that = (CustomUserDetails) o; + return firstName.equals(that.firstName) && lastName.equals(that.lastName) && email.equals(that.email); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), firstName, lastName, email); + } + + public static class Builder { + + private String firstName; + private String lastName; + private String email; + private String username; + private String password; + private Collection authorities; + + public Builder withFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public Builder withLastName(String lastName) { + this.lastName = lastName; + return this; + } + + public Builder withEmail(String email) { + this.email = email; + return this; + } + + public Builder withUsername(String username) { + this.username = username; + return this; + } + + public Builder withPassword(String password) { + this.password = password; + return this; + } + + public Builder withAuthorities(Collection authorities) { + this.authorities = authorities; + return this; + } + + public CustomUserDetails build() { + return new CustomUserDetails(this); + } + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetailsService.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetailsService.java new file mode 100644 index 0000000000..e84f9eac55 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/CustomUserDetailsService.java @@ -0,0 +1,52 @@ +package com.baeldung.customuserdetails; + +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + + private final PasswordEncoder passwordEncoder; + private final Map userRegistry = new HashMap<>(); + + public CustomUserDetailsService(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + @PostConstruct + public void init() { + userRegistry.put("user", new CustomUserDetails.Builder().withFirstName("Mark") + .withLastName("Johnson") + .withEmail("mark.johnson@email.com") + .withUsername("user") + .withPassword(passwordEncoder.encode("password")) + .withAuthorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))) + .build()); + userRegistry.put("admin", new CustomUserDetails.Builder().withFirstName("James") + .withLastName("Davis") + .withEmail("james.davis@email.com") + .withUsername("admin") + .withPassword(passwordEncoder.encode("admin")) + .withAuthorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_ADMIN"))) + .build()); + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + final CustomUserDetails userDetails = userRegistry.get(username); + if (userDetails == null) { + throw new UsernameNotFoundException(username); + } + return userDetails; + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/PasswordEncoderConfiguration.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/PasswordEncoderConfiguration.java new file mode 100644 index 0000000000..fa19b62577 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/PasswordEncoderConfiguration.java @@ -0,0 +1,15 @@ +package com.baeldung.customuserdetails; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfiguration { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SecurityConfiguration.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SecurityConfiguration.java new file mode 100644 index 0000000000..5d5863a564 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SecurityConfiguration.java @@ -0,0 +1,38 @@ +package com.baeldung.customuserdetails; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + private final UserDetailsService userDetailsService; + + public SecurityConfiguration(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.userDetailsService(userDetailsService) + .authorizeRequests() + .anyRequest() + .authenticated() + .and() + .formLogin() + .loginPage("/login") + .permitAll() + .successForwardUrl("/index") + .and() + .logout() + .permitAll() + .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutSuccessUrl("/login"); + } + +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplication.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplication.java new file mode 100644 index 0000000000..35cbc77552 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.customuserdetails; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSecurityThymeleafApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityThymeleafApplication.class, args); + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/ViewController.java b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/ViewController.java new file mode 100644 index 0000000000..bc4c41392d --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/java/com/baeldung/customuserdetails/ViewController.java @@ -0,0 +1,21 @@ +package com.baeldung.customuserdetails; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ViewController { + + @RequestMapping("/login") + public String login() { + return "login"; + } + + @RequestMapping({ "/index", "/" }) + public String index() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return "userdetails"; + } +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/main/resources/templates/userdetails.html b/spring-security-modules/spring-security-web-thymeleaf/src/main/resources/templates/userdetails.html new file mode 100644 index 0000000000..5963fbc29e --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/main/resources/templates/userdetails.html @@ -0,0 +1,25 @@ + + + +Welcome to Spring Security Thymeleaf tutorial + + +

Welcome

+

Spring Security Thymeleaf tutorial

+
Text visible to user.
+
Text visible to admin.
+
Text visible only to + authenticated users.
+ Authenticated username: +
+ Authenticated user's firstName: +
+ Authenticated user's lastName: +
+ Authenticated user's email: +
+ Authenticated user roles: +
+ + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplicationIntegrationTest.java b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplicationIntegrationTest.java new file mode 100644 index 0000000000..c3b11e648a --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/SpringSecurityThymeleafApplicationIntegrationTest.java @@ -0,0 +1,29 @@ +package com.baeldung.customuserdetails; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.assertNotNull; + +import com.baeldung.customuserdetails.ViewController; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringSecurityThymeleafApplicationIntegrationTest { + + @Autowired + ViewController viewController; + @Autowired + WebApplicationContext wac; + + @Test + public void whenConfigured_thenLoadsContext() { + assertNotNull(viewController); + assertNotNull(wac); + } + +} diff --git a/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/ViewControllerIntegrationTest.java b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/ViewControllerIntegrationTest.java new file mode 100644 index 0000000000..73d4bda112 --- /dev/null +++ b/spring-security-modules/spring-security-web-thymeleaf/src/test/java/com/baeldung/customuserdetails/ViewControllerIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.customuserdetails; + +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.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +import com.baeldung.customuserdetails.PasswordEncoderConfiguration; + +@RunWith(SpringRunner.class) +@WebMvcTest +@Import(PasswordEncoderConfiguration.class) +public class ViewControllerIntegrationTest { + + @Autowired + private WebApplicationContext context; + MockMvc mvc; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .build(); + } + + @Test + public void givenUser_whenPerformingGet_thenReturnsIndex() throws Exception { + mvc.perform(get("/index").with(user("user").password("password"))).andExpect(status().isOk()).andExpect(view().name("userdetails")); + } + +} From d24f73002a2c21f39ffb012fb96f85fb64020259 Mon Sep 17 00:00:00 2001 From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com> Date: Thu, 4 Aug 2022 10:49:11 +0200 Subject: [PATCH 28/39] Load Image With Spring Boot and Thymeleaf (#12486) * Load Image With Spring Boot and Thymeleaf * Load Image With Spring Boot and Thymeleaf --- .../imageupload/UploadController.java | 31 +++++++++++++++++++ .../src/main/resources/application.properties | 4 ++- .../templates/imageupload/index.html | 25 +++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/imageupload/UploadController.java create mode 100644 spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/imageupload/index.html diff --git a/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/imageupload/UploadController.java b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/imageupload/UploadController.java new file mode 100644 index 0000000000..d3ccc82323 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/src/main/java/com/baeldung/thymeleaf/imageupload/UploadController.java @@ -0,0 +1,31 @@ +package com.baeldung.thymeleaf.imageupload; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Controller public class UploadController { + + public static String UPLOAD_DIRECTORY = System.getProperty("user.dir") + "/uploads"; + + @GetMapping("/uploadimage") public String displayUploadForm() { + return "imageupload/index"; + } + + @PostMapping("/upload") public String uploadImage(Model model, @RequestParam("image") MultipartFile file) throws IOException { + StringBuilder fileNames = new StringBuilder(); + Path fileNameAndPath = Paths.get(UPLOAD_DIRECTORY, file.getOriginalFilename()); + fileNames.append(file.getOriginalFilename()); + Files.write(fileNameAndPath, file.getBytes()); + model.addAttribute("msg", "Uploaded images: " + fileNames.toString()); + return "imageupload/index"; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties b/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties index b09232bb1b..7a5b9c207d 100644 --- a/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties +++ b/spring-web-modules/spring-thymeleaf-5/src/main/resources/application.properties @@ -1 +1,3 @@ -#spring.thymeleaf.prefix=classpath:/templates-2/ \ No newline at end of file +#spring.thymeleaf.prefix=classpath:/templates-2/ +spring.servlet.multipart.max-file-size = 5MB +spring.servlet.multipart.max-request-size = 5MB \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/imageupload/index.html b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/imageupload/index.html new file mode 100644 index 0000000000..e129a123e9 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-5/src/main/resources/templates/imageupload/index.html @@ -0,0 +1,25 @@ + + + + + + +
+
+
+
+

Upload Image Example

+

+
+
+ +
+ +
+ +
+
+
+
+ + \ No newline at end of file From 0dc36fdb4369424cee2eaced40314ac831db89fa Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Fri, 5 Aug 2022 00:59:43 +0530 Subject: [PATCH 29/39] BAEL-5230 Added code and test for Fauna IoT application article (#12554) * BAEL-5230 Added code and test for Fauna IoT application article * BAEL-5230 Removed secrets from the codebase * BAEL-5230 Removed spring-boot-configuration-processor --- persistence-modules/fauna/pom.xml | 11 +++- .../com/baeldung/healthapp/FaunaClients.java | 42 ++++++++++++++ .../healthapp/FaunaHealthApplication.java | 13 +++++ .../baeldung/healthapp/domain/HealthData.java | 17 ++++++ .../service/DefaultGeoLocationService.java | 12 ++++ .../service/DefaultHealthService.java | 58 +++++++++++++++++++ .../healthapp/service/GeoLocationService.java | 6 ++ .../healthapp/service/HealthService.java | 10 ++++ .../src/main/resources/application.properties | 10 ++++ .../DefaultHealthServiceManualTest.java | 55 ++++++++++++++++++ 10 files changed, 231 insertions(+), 3 deletions(-) create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java create mode 100644 persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java diff --git a/persistence-modules/fauna/pom.xml b/persistence-modules/fauna/pom.xml index 8c985e0b7c..a00dd0eb8d 100644 --- a/persistence-modules/fauna/pom.xml +++ b/persistence-modules/fauna/pom.xml @@ -3,11 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung fauna - 0.0.1-SNAPSHOT fauna - Blogging Service built with FaunaDB + Code snippets for FaunaDB articles com.baeldung @@ -41,6 +39,13 @@ spring-security-test test + + + + org.projectlombok + lombok + provided + diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java new file mode 100644 index 0000000000..c4e1d52b5b --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java @@ -0,0 +1,42 @@ +package com.baeldung.healthapp; + +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import com.faunadb.client.FaunaClient; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@ConfigurationProperties +@Component +public class FaunaClients { + + private final Map faunaConnections = new HashMap<>(); + private final Map faunaSecrets = new HashMap<>(); + + public FaunaClient getFaunaClient(String region) throws MalformedURLException { + + String faunaUrl = faunaConnections.get(region); + String faunaSecret = faunaSecrets.get(region); + + log.info("Creating Fauna Client for Region:{} with URL:{}", region, faunaUrl); + + return FaunaClient.builder() + .withEndpoint(faunaUrl) + .withSecret(faunaSecret) + .build(); + } + + public Map getFaunaConnections() { + return faunaConnections; + } + + public Map getFaunaSecrets() { + return faunaSecrets; + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java new file mode 100644 index 0000000000..ac09e4cd36 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.healthapp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class FaunaHealthApplication { + + public static void main(String[] args) { + SpringApplication.run(FaunaHealthApplication.class, args); + } + +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java new file mode 100644 index 0000000000..9ee320c3d5 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java @@ -0,0 +1,17 @@ +package com.baeldung.healthapp.domain; + +import java.time.ZonedDateTime; + +public record HealthData( + + String userId, + + float temperature, + float pulseRate, + int bpSystolic, + int bpDiastolic, + + double latitude, + double longitude, + ZonedDateTime timestamp) { +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java new file mode 100644 index 0000000000..b643714972 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java @@ -0,0 +1,12 @@ +package com.baeldung.healthapp.service; + +import org.springframework.stereotype.Component; + +@Component +public class DefaultGeoLocationService implements GeoLocationService { + + @Override + public String getRegion(double latitude, double longitude) { + return "EU"; + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java new file mode 100644 index 0000000000..8e44b4b243 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java @@ -0,0 +1,58 @@ +package com.baeldung.healthapp.service; + +import static com.faunadb.client.query.Language.Collection; +import static com.faunadb.client.query.Language.Create; +import static com.faunadb.client.query.Language.Now; +import static com.faunadb.client.query.Language.Obj; +import static com.faunadb.client.query.Language.Value; + +import java.net.MalformedURLException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.healthapp.FaunaClients; +import com.baeldung.healthapp.domain.HealthData; +import com.faunadb.client.FaunaClient; +import com.faunadb.client.types.Value; + +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class DefaultHealthService implements HealthService { + + @Autowired + private GeoLocationService geoLocationService; + + @Autowired + private FaunaClients faunaClients; + + @Override + public void process(HealthData healthData) throws MalformedURLException, InterruptedException, ExecutionException { + + String region = geoLocationService.getRegion( // + healthData.latitude(), // + healthData.longitude()); + + FaunaClient faunaClient = faunaClients.getFaunaClient(region); + + Value queryResponse = faunaClient.query( + Create(Collection("healthdata"), + Obj("data", + Obj(Map.of( + "userId", Value(healthData.userId()), + "temperature", Value(healthData.temperature()), + "pulseRate", Value(healthData.pulseRate()), + "bpSystolic", Value(healthData.bpSystolic()), + "bpDiastolic", Value(healthData.bpDiastolic()), + "latitude", Value(healthData.latitude()), + "longitude", Value(healthData.longitude()), + "timestamp", Now())))) + ).get(); + + log.info("Query response received from Fauna: {}", queryResponse); + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java new file mode 100644 index 0000000000..43a3204610 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java @@ -0,0 +1,6 @@ +package com.baeldung.healthapp.service; + +public interface GeoLocationService { + + String getRegion(double latitude, double longitude); +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java new file mode 100644 index 0000000000..eadf12cc08 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java @@ -0,0 +1,10 @@ +package com.baeldung.healthapp.service; + +import java.net.MalformedURLException; +import java.util.concurrent.ExecutionException; + +import com.baeldung.healthapp.domain.HealthData; + +public interface HealthService { + void process(HealthData healthData) throws MalformedURLException, InterruptedException, ExecutionException; +} diff --git a/persistence-modules/fauna/src/main/resources/application.properties b/persistence-modules/fauna/src/main/resources/application.properties index e69de29bb2..0f50dfa8b3 100644 --- a/persistence-modules/fauna/src/main/resources/application.properties +++ b/persistence-modules/fauna/src/main/resources/application.properties @@ -0,0 +1,10 @@ +# Fauna Blog Service +fauna.region=EU +fauna.secret= + +# Fauna Health App +fauna-connections.EU=https://db.eu.fauna.com/ +fauna-secrets.EU=eu-secret + +fauna-connections.US=https://db.us.fauna.com/ +fauna-secrets.US=us-secret \ No newline at end of file diff --git a/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java b/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java new file mode 100644 index 0000000000..f77eb623b6 --- /dev/null +++ b/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java @@ -0,0 +1,55 @@ +package com.baeldung.healthapp.service; + +import static org.mockito.Mockito.when; + +import java.net.MalformedURLException; +import java.time.ZonedDateTime; +import java.util.concurrent.ExecutionException; + +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.mock.mockito.MockBean; + +import com.baeldung.healthapp.FaunaHealthApplication; +import com.baeldung.healthapp.domain.HealthData; + +@SpringBootTest(classes = FaunaHealthApplication.class) +class DefaultHealthServiceManualTest { + + @Autowired + private DefaultHealthService defaultHealthService; + + @MockBean + private GeoLocationService geoLocationService; + + @Test + void givenEURegion_whenProcess_thenRequestSentToEURegion() throws MalformedURLException, InterruptedException, ExecutionException { + + HealthData healthData = new HealthData("user-1-eu", // + 37.5f, // + 99f, // + 120, 80, // + 51.50, -0.07, // + ZonedDateTime.now()); + + when(geoLocationService.getRegion(51.50, -0.07)).thenReturn("EU"); + + defaultHealthService.process(healthData); + } + + @Test + void givenUSRegion_whenProcess_thenRequestSentToUSRegion() throws MalformedURLException, InterruptedException, ExecutionException { + + HealthData healthData = new HealthData("user-1-us", // + 38.0f, // + 100f, // + 115, 85, // + 40.75, -74.30, // + ZonedDateTime.now()); + + when(geoLocationService.getRegion(40.75, -74.30)).thenReturn("US"); + + defaultHealthService.process(healthData); + } +} From 717e3fafdb205fed09970e24b8858437cf94e48a Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Fri, 5 Aug 2022 01:19:05 +0530 Subject: [PATCH 30/39] JAVA-13629 More fixes and updates (#12566) --- .../api/{MessageApi.java => MessageDTO.java} | 2 +- .../baeldung/app/rest/MessageController.java | 4 +-- .../app/rest/MessageControllerUnitTest.java | 28 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) rename testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/{MessageApi.java => MessageDTO.java} (94%) diff --git a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageApi.java b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageDTO.java similarity index 94% rename from testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageApi.java rename to testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageDTO.java index edbe5a1d5a..1d9da244b0 100644 --- a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageApi.java +++ b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/api/MessageDTO.java @@ -1,6 +1,6 @@ package com.baeldung.app.api; -public class MessageApi { +public class MessageDTO { private String from; private String to; private String text; diff --git a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/MessageController.java b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/MessageController.java index e23c2e7607..6911197197 100644 --- a/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/MessageController.java +++ b/testing-modules/mockito-simple/src/main/java/com/baeldung/app/rest/MessageController.java @@ -1,6 +1,6 @@ package com.baeldung.app.rest; -import com.baeldung.app.api.MessageApi; +import com.baeldung.app.api.MessageDTO; import com.baeldung.domain.model.Message; import com.baeldung.domain.service.MessageService; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +21,7 @@ public class MessageController { private MessageService messageService; @PostMapping - public Message createMessage (@RequestBody MessageApi messageDTO) { + public Message createMessage (@RequestBody MessageDTO messageDTO) { Message message = new Message(); message.setText(messageDTO.getText()); message.setFrom(messageDTO.getFrom()); diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java index ae368c4c34..1bfbeecfec 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/app/rest/MessageControllerUnitTest.java @@ -11,7 +11,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import com.baeldung.app.api.MessageApi; +import com.baeldung.app.api.MessageDTO; import com.baeldung.domain.model.Message; import com.baeldung.domain.service.MessageService; import com.baeldung.domain.util.MessageMatcher; @@ -19,32 +19,32 @@ import com.baeldung.domain.util.MessageMatcher; @RunWith(MockitoJUnitRunner.class) public class MessageControllerUnitTest { + @InjectMocks + private MessageController messageController; + @Mock private MessageService messageService; - @InjectMocks - private MessageController messageController; - @Test public void givenMsg_whenVerifyUsingAnyMatcher_thenOk() { - MessageApi messageApi = new MessageApi(); - messageApi.setFrom("me"); - messageApi.setTo("you"); - messageApi.setText("Hello, you!"); + MessageDTO messageDTO = new MessageDTO(); + messageDTO.setFrom("me"); + messageDTO.setTo("you"); + messageDTO.setText("Hello, you!"); - messageController.createMessage(messageApi); + messageController.createMessage(messageDTO); verify(messageService, times(1)).deliverMessage(any(Message.class)); } @Test public void givenMsg_whenVerifyUsingMessageMatcher_thenOk() { - MessageApi messageApi = new MessageApi(); - messageApi.setFrom("me"); - messageApi.setTo("you"); - messageApi.setText("Hello, you!"); + MessageDTO messageDTO = new MessageDTO(); + messageDTO.setFrom("me"); + messageDTO.setTo("you"); + messageDTO.setText("Hello, you!"); - messageController.createMessage(messageApi); + messageController.createMessage(messageDTO); Message message = new Message(); message.setFrom("me"); From 4dd55bc5170102b0d362d84a116f10d33d8fb7c3 Mon Sep 17 00:00:00 2001 From: panagiotiskakos Date: Sat, 6 Aug 2022 10:30:03 +0300 Subject: [PATCH 31/39] [JAVA-13838] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a4f6a744ea..2264caa99f 100644 --- a/pom.xml +++ b/pom.xml @@ -1381,7 +1381,7 @@ 1.2 2.3.1 1.2 - 2.13.0 + 2.13.3 1.4 1.8.1 5.8.1 From eb91f373ce0095d6a358ece5824e8a36fec079bc Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Sat, 6 Aug 2022 18:35:30 +0530 Subject: [PATCH 32/39] JAVA-13606 Remove mention of Mockito 2 as a separate library (#12571) --- testing-modules/mockito/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/mockito/README.md b/testing-modules/mockito/README.md index 2870d1afcf..46795d2fe4 100644 --- a/testing-modules/mockito/README.md +++ b/testing-modules/mockito/README.md @@ -1,7 +1,7 @@ ### Relevant articles - [Mockito’s Java 8 Features](https://www.baeldung.com/mockito-2-java-8) -- [Lazy Verification with Mockito 2](https://www.baeldung.com/mockito-2-lazy-verification) +- [Lazy Verification with Mockito](https://www.baeldung.com/mockito-2-lazy-verification) - [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception) - [Mockito and Fluent APIs](https://www.baeldung.com/mockito-fluent-apis) - [Mocking the ObjectMapper readValue() Method](https://www.baeldung.com/mockito-mock-jackson-read-value) From ba9947633050b7fea2640326e2e59cf098ff6eb6 Mon Sep 17 00:00:00 2001 From: hesamghiasi Date: Sat, 6 Aug 2022 18:08:59 +0430 Subject: [PATCH 33/39] fixing time ago unit tests (#12560) * adding getCurrentTime method to TimeAgoCalculatorUnitTest in order to always return the same time and avoid problems related to reading date from local system. adding two methods to TimeAgoCalculator to always return the same date as the current date in order to avoid problems related to reading current time from local host. One of these two methods accepts time zone * adding getCurrentTime method to TimeAgoCalculatorUnitTest in order to always return the same time and avoid problems related to reading date from local system. adding two methods to TimeAgoCalculator to always return the same date as the current date in order to avoid problems related to reading current time from local host. One of these two methods accepts time zone correcting some formattings adding comments in code to clarify adding of getCurrentTime methods * reverting changes to ZuulConfig --- .../timeago/version7/TimeAgoCalculator.java | 29 ++++++-- .../timeago/version8/TimeAgoCalculator.java | 12 +++- .../version7/TimeAgoCalculatorUnitTest.java | 70 +++++++++++-------- .../version8/TimeAgoCalculatorUnitTest.java | 28 +++++--- 4 files changed, 89 insertions(+), 50 deletions(-) diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java index e09880f1ee..00f1d75029 100644 --- a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java +++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version7/TimeAgoCalculator.java @@ -2,6 +2,7 @@ package com.baeldung.timeago.version7; import java.util.Date; import java.util.TimeZone; +import java.util.Calendar; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -12,16 +13,30 @@ import org.joda.time.format.PeriodFormatterBuilder; public class TimeAgoCalculator { + private static long getCurrentTime() { + Calendar calendar = Calendar.getInstance(); + calendar.set(2020, 1, 1, 12, 0, 0); + return calendar.getTimeInMillis(); + //We return a fixed date and time in order to avoid issues related to getting time from local in unit tests. + //return System.currentTimeMillis(); + } + + private static long getCurrentTimeByTimeZone(TimeZone zone) { + Calendar calendar = Calendar.getInstance(zone); + calendar.set(2020, 1, 1, 12, 0, 0); + return calendar.getTimeInMillis(); + //We return a fixed date and time in order to avoid issues related to getting time from local in unit tests. + //return Calendar.getInstance(zone).getTimeInMillis(); + } + public static String calculateTimeAgoByTimeGranularity(Date pastTime, TimeGranularity granularity) { - Date currentTime = new Date(); - long timeDifferenceInMillis = currentTime.getTime() - pastTime.getTime(); + long timeDifferenceInMillis = getCurrentTime() - pastTime.getTime(); return timeDifferenceInMillis / granularity.toMillis() + " " + granularity.name() .toLowerCase() + " ago"; } public static String calculateHumanFriendlyTimeAgo(Date pastTime) { - Date currentTime = new Date(); - long timeDifferenceInMillis = currentTime.getTime() - pastTime.getTime(); + long timeDifferenceInMillis = getCurrentTime() - pastTime.getTime(); if (timeDifferenceInMillis / TimeGranularity.DECADES.toMillis() > 0) return "several decades ago"; else if (timeDifferenceInMillis / TimeGranularity.YEARS.toMillis() > 0) @@ -41,7 +56,7 @@ public class TimeAgoCalculator { } public static String calculateExactTimeAgoWithJodaTime(Date pastTime) { - Period period = new Period(new DateTime(pastTime.getTime()), new DateTime()); + Period period = new Period(new DateTime(pastTime.getTime()), new DateTime(getCurrentTime())); PeriodFormatter formatter = new PeriodFormatterBuilder().appendYears() .appendSuffix(" year ", " years ") .appendSeparator("and ") @@ -67,7 +82,7 @@ public class TimeAgoCalculator { } public static String calculateHumanFriendlyTimeAgoWithJodaTime(Date pastTime) { - Period period = new Period(new DateTime(pastTime.getTime()), new DateTime()); + Period period = new Period(new DateTime(pastTime.getTime()), new DateTime(getCurrentTime())); if (period.getYears() != 0) return "several years ago"; else if (period.getMonths() != 0) @@ -86,7 +101,7 @@ public class TimeAgoCalculator { public static String calculateZonedTimeAgoWithJodaTime(Date pastTime, TimeZone zone) { DateTimeZone dateTimeZone = DateTimeZone.forID(zone.getID()); - Period period = new Period(new DateTime(pastTime.getTime(), dateTimeZone), new DateTime(dateTimeZone)); + Period period = new Period(new DateTime(pastTime.getTime(), dateTimeZone), new DateTime(getCurrentTimeByTimeZone(zone))); return PeriodFormat.getDefault() .print(period); } diff --git a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java index 392cfa54fa..4395e70ba1 100644 --- a/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java +++ b/core-java-modules/core-java-date-operations-2/src/main/java/com/baeldung/timeago/version8/TimeAgoCalculator.java @@ -12,9 +12,17 @@ import org.ocpsoft.prettytime.PrettyTime; public class TimeAgoCalculator { + private static LocalDateTime getCurrentTimeByTimeZone(ZoneId zone) { + LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 12, 0, 0); + return localDateTime.atZone(zone) + .toLocalDateTime(); + //We return a fixed date and time in order to avoid issues related to getting time from local in unit tests. + //return LocalDateTime.now(zone); + } + public static String calculateTimeAgoWithPeriodAndDuration(LocalDateTime pastTime, ZoneId zone) { - Period period = Period.between(pastTime.toLocalDate(), LocalDate.now(zone)); - Duration duration = Duration.between(pastTime, LocalDateTime.now(zone)); + Period period = Period.between(pastTime.toLocalDate(), getCurrentTimeByTimeZone(zone).toLocalDate()); + Duration duration = Duration.between(pastTime, getCurrentTimeByTimeZone(zone)); if (period.getYears() != 0) return "several years ago"; else if (period.getMonths() != 0) diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java index b41533aa7e..d006b72ed2 100644 --- a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java +++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version7/TimeAgoCalculatorUnitTest.java @@ -1,56 +1,64 @@ package com.baeldung.timeago.version7; import java.util.Date; +import java.util.Calendar; import org.junit.Assert; import org.junit.Test; public class TimeAgoCalculatorUnitTest { - // fixing tests in BAEL-5647 - //@Test + private long getCurrentTime() { + Calendar calendar = Calendar.getInstance(); + calendar.set(2020, 1, 1, 12, 0, 0); + return calendar.getTimeInMillis(); + //We return a fixed date and time in order to avoid issues related to getting time from local in unit tests. + //return System.currentTimeMillis(); + } + + @Test public void timeAgoByTimeGranularityTest() { long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; - Assert.assertEquals("5 seconds ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 1000)), TimeGranularity.SECONDS)); - Assert.assertEquals("5 minutes ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 60 * 1000)), TimeGranularity.MINUTES)); - Assert.assertEquals("5 hours ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)), TimeGranularity.HOURS)); - Assert.assertEquals("5 days ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)), TimeGranularity.DAYS)); - Assert.assertEquals("5 months ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)), TimeGranularity.MONTHS)); - Assert.assertEquals("5 weeks ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 7)), TimeGranularity.WEEKS)); - Assert.assertEquals("5 years ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)), TimeGranularity.YEARS)); - Assert.assertEquals("5 decades ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365 * 10)), TimeGranularity.DECADES)); + Assert.assertEquals("5 seconds ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * 1000)), TimeGranularity.SECONDS)); + Assert.assertEquals("5 minutes ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * 60 * 1000)), TimeGranularity.MINUTES)); + Assert.assertEquals("5 hours ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * 60 * 60 * 1000)), TimeGranularity.HOURS)); + Assert.assertEquals("5 days ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS)), TimeGranularity.DAYS)); + Assert.assertEquals("5 months ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 30)), TimeGranularity.MONTHS)); + Assert.assertEquals("5 weeks ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 7)), TimeGranularity.WEEKS)); + Assert.assertEquals("5 years ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 365)), TimeGranularity.YEARS)); + Assert.assertEquals("5 decades ago", TimeAgoCalculator.calculateTimeAgoByTimeGranularity(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 365 * 10)), TimeGranularity.DECADES)); } - //@Test + @Test public void humanFriendlyTimeAgoTest() { long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; - Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 1000)))); - Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 60 * 1000)))); - Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)))); - Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)))); - Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)))); - Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (3 * DAY_IN_MILLIS * 7)))); - Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)))); - Assert.assertEquals("several decades ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365 * 10)))); + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * 1000)))); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * 60 * 1000)))); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * 60 * 60 * 1000)))); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS)))); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 30)))); + Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (3 * DAY_IN_MILLIS * 7)))); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 365)))); + Assert.assertEquals("several decades ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgo(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 365 * 10)))); } - //@Test + @Test public void calculateExactTimeAgoWithJodaTimeTest() { - Assert.assertEquals("5 hours and 15 minutes and 3 seconds", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000 + 15 * 60 * 1000 + 3 * 1000)))); - Assert.assertEquals("5 hours and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); - Assert.assertEquals("2 days and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (2 * 24 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); + Assert.assertEquals("5 hours and 15 minutes and 3 seconds", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * 60 * 60 * 1000 + 15 * 60 * 1000 + 3 * 1000)))); + Assert.assertEquals("5 hours and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); + Assert.assertEquals("2 days and 1 minute and 1 second", TimeAgoCalculator.calculateExactTimeAgoWithJodaTime(new Date(getCurrentTime() - (2 * 24 * 60 * 60 * 1000 + 1 * 60 * 1000 + 1 * 1000)))); } - //@Test + @Test public void calculateHumanFriendlyTimeAgoWithJodaTimeTest() { long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; - Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 1000)))); - Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 1000)))); - Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * 60 * 60 * 1000)))); - Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)))); - Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)))); - Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (3 * DAY_IN_MILLIS * 7)))); - Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)))); + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * 1000)))); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * 60 * 1000)))); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * 60 * 60 * 1000)))); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS)))); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 30)))); + Assert.assertEquals("several weeks ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (3 * DAY_IN_MILLIS * 7)))); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateHumanFriendlyTimeAgoWithJodaTime(new Date(getCurrentTime() - (5 * DAY_IN_MILLIS * 365)))); } } diff --git a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java index 5fb8512a7e..81ad547a50 100644 --- a/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java +++ b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/timeago/version8/TimeAgoCalculatorUnitTest.java @@ -1,7 +1,9 @@ package com.baeldung.timeago.version8; +import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; +import java.time.Period; import java.time.ZoneId; import org.junit.Assert; @@ -9,16 +11,22 @@ import org.junit.Test; public class TimeAgoCalculatorUnitTest { - // fixing test in BAEL-5647 - //@Test + private LocalDateTime getCurrentTime() { + LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 12, 0, 0); + return localDateTime.atZone(ZoneId.systemDefault()) + .toLocalDateTime(); + //We return a fixed date and time in order to avoid issues related to getting time from local in unit tests. + //return LocalDateTime.now(zone); + } + + @Test public void calculateTimeAgoWithPeriodAndDurationTest() { - long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; - Assert.assertEquals("moments ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several seconds ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 60 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * 60 * 60 * 1000)), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several days ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS)), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several months ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 30)), ZoneId.systemDefault()), ZoneId.systemDefault())); - Assert.assertEquals("several years ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis() - (5 * DAY_IN_MILLIS * 365)), ZoneId.systemDefault()), ZoneId.systemDefault())); + Assert.assertEquals("moments ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime(), ZoneId.systemDefault())); + Assert.assertEquals("several seconds ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Duration.ofSeconds(5)), ZoneId.systemDefault())); + Assert.assertEquals("several minutes ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Duration.ofMinutes(5)), ZoneId.systemDefault())); + Assert.assertEquals("several hours ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Duration.ofHours(5)), ZoneId.systemDefault())); + Assert.assertEquals("several days ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Period.ofDays(5)), ZoneId.systemDefault())); + Assert.assertEquals("several months ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Period.ofMonths(5)), ZoneId.systemDefault())); + Assert.assertEquals("several years ago", TimeAgoCalculator.calculateTimeAgoWithPeriodAndDuration(getCurrentTime().minus(Period.ofYears(5)), ZoneId.systemDefault())); } } From 2db5fcea1e9fbb31a611b25f05358b9b491d6d9e Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 6 Aug 2022 23:56:44 +0530 Subject: [PATCH 34/39] JAVA-13416 Converting to *LiveTest as it makes live call to httpbin URLs (#12573) --- .../auth/{HttpClientUnitTest.java => HttpClientLiveTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/{HttpClientUnitTest.java => HttpClientLiveTest.java} (97%) diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientUnitTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientLiveTest.java similarity index 97% rename from core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientUnitTest.java rename to core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientLiveTest.java index 0ccb6e5a54..01d580bc65 100644 --- a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientUnitTest.java +++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/auth/HttpClientLiveTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; -public class HttpClientUnitTest { +public class HttpClientLiveTest { @Test public void sendRquestWithAuthHeader() throws Exception { From ef0b7ea20c6a855c2101c46fcac885f03bd3c434 Mon Sep 17 00:00:00 2001 From: Muhammad Abdullah Azam Khan Date: Mon, 8 Aug 2022 08:03:20 +0400 Subject: [PATCH 35/39] Update KafkaApplication.java (#12424) * Update KafkaApplication.java Added partition offset to the listener so that it can start consuming the messages from the beginning of the topic. * Revert "Update KafkaApplication.java" This reverts commit 28801f85174af8bf2d2bb89e1fb39b52c49a6cf0. * Counting Messages 1. Counting messages from Producer offset 2. Counting messages from Consumer 3. Rest APIs to view the count * Refactoring * Adding 3rd programmatic method to count number of messages in Kafka topic * Removing irrelevant code * Server port removed --- .../countingmessages/Application.java | 11 ++++ .../KafkaCountingMessagesComponent.java | 52 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 spring-kafka/src/main/java/com/baeldung/countingmessages/Application.java create mode 100644 spring-kafka/src/main/java/com/baeldung/countingmessages/KafkaCountingMessagesComponent.java diff --git a/spring-kafka/src/main/java/com/baeldung/countingmessages/Application.java b/spring-kafka/src/main/java/com/baeldung/countingmessages/Application.java new file mode 100644 index 0000000000..7649494438 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/countingmessages/Application.java @@ -0,0 +1,11 @@ +package com.baeldung.countingmessages; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args){ + SpringApplication.run(Application.class,args); + } +} diff --git a/spring-kafka/src/main/java/com/baeldung/countingmessages/KafkaCountingMessagesComponent.java b/spring-kafka/src/main/java/com/baeldung/countingmessages/KafkaCountingMessagesComponent.java new file mode 100644 index 0000000000..91ce1b0cbe --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/countingmessages/KafkaCountingMessagesComponent.java @@ -0,0 +1,52 @@ +package com.baeldung.countingmessages; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + + +@Component +public class KafkaCountingMessagesComponent { + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + public static Map props = new HashMap<>(); + + @PostConstruct + public void init(){ + System.out.println(getTotalNumberOfMessagesInATopic("baeldung")); + } + + public Long getTotalNumberOfMessagesInATopic(String topic){ + org.apache.kafka.clients.consumer.KafkaConsumer consumer = new org.apache.kafka.clients.consumer.KafkaConsumer<>(getProps()); + List partitions = consumer.partitionsFor(topic).stream() + .map(p -> new TopicPartition(topic, p.partition())) + .collect(Collectors.toList()); + consumer.assign(partitions); + consumer.seekToEnd(Collections.emptySet()); + Map endPartitions = partitions.stream() + .collect(Collectors.toMap(Function.identity(), consumer::position)); + return partitions.stream().mapToLong(p -> endPartitions.get(p)).sum(); + } + + public Map getProps() { + if (props.isEmpty()) { + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, "20971520"); + props.put(ConsumerConfig.FETCH_MAX_BYTES_CONFIG, "20971520"); + } + return props; + } +} From 9528c5165484db7221364bf735734308f9c178ef Mon Sep 17 00:00:00 2001 From: Sameer Date: Mon, 8 Aug 2022 16:38:34 +0530 Subject: [PATCH 36/39] Articles/bael 4903 (#12572) * conditional dependency demo * added Gradle 7 submodule Co-authored-by: s9m33r --- .../conditional-dependency-demo/.gitignore | 37 +++ .../build.gradle.kts | 21 ++ .../consumer1/build.gradle.kts | 25 ++ .../consumer2/build.gradle.kts | 30 +++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59821 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + .../conditional-dependency-demo/gradlew | 234 ++++++++++++++++++ .../conditional-dependency-demo/gradlew.bat | 89 +++++++ .../provider1/build.gradle.kts | 19 ++ .../provider2/build.gradle.kts | 19 ++ .../settings.gradle.kts | 5 + .../ConditionalDependencyDemoApplication.java | 15 ++ .../src/main/resources/application.properties | 1 + ...itionalDependencyDemoApplicationTests.java | 13 + gradle-modules/settings.gradle | 1 + 15 files changed, 514 insertions(+) create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/.gitignore create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/build.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/consumer1/build.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/consumer2/build.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.properties create mode 100755 gradle-modules/gradle-7/conditional-dependency-demo/gradlew create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/gradlew.bat create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/provider1/build.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/provider2/build.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/settings.gradle.kts create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/src/main/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplication.java create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/src/main/resources/application.properties create mode 100644 gradle-modules/gradle-7/conditional-dependency-demo/src/test/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplicationTests.java diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/.gitignore b/gradle-modules/gradle-7/conditional-dependency-demo/.gitignore new file mode 100644 index 0000000000..c2065bc262 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/build.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/build.gradle.kts new file mode 100644 index 0000000000..95601a160d --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("org.springframework.boot") version "2.7.2" + id("io.spring.dependency-management") version "1.0.11.RELEASE" + id("java") +} + +group = "com.baeldung.gradle" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter:2.7.2") + testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.2") +} + +tasks.getByName("test") { + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/consumer1/build.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/consumer1/build.gradle.kts new file mode 100644 index 0000000000..9858c5b139 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/consumer1/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + id("java") +} + +group = "com.baeldung.gradle" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.7.0") + + if(project.hasProperty("isLocal")) { + implementation("com.baeldung.gradle:provider1") + } else { + implementation("com.baeldung.gradle:provider2") + } +} + +tasks.getByName("test") { + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/consumer2/build.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/consumer2/build.gradle.kts new file mode 100644 index 0000000000..2031aea59c --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/consumer2/build.gradle.kts @@ -0,0 +1,30 @@ +plugins { + id("java") +} + +group = "com.baeldung.gradle" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +configurations.all { + resolutionStrategy.dependencySubstitution { + if (project.hasProperty("isLocal")) + substitute(project(":provider1")) + .using(project(":provider2")) + .because("Project property override(isLocal).") + } +} + +dependencies { + implementation(project(":provider1")) + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") +} + +tasks.getByName("test") { + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.jar b/gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..41d9927a4d4fb3f96a785543079b8df6723c946b GIT binary patch literal 59821 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 literal 0 HcmV?d00001 diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.properties b/gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..00e33edef6 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/gradlew b/gradle-modules/gradle-7/conditional-dependency-demo/gradlew new file mode 100755 index 0000000000..1b6c787337 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/gradlew.bat b/gradle-modules/gradle-7/conditional-dependency-demo/gradlew.bat new file mode 100644 index 0000000000..107acd32c4 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/provider1/build.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/provider1/build.gradle.kts new file mode 100644 index 0000000000..d3dcd96b08 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/provider1/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("java") +} + +group = "com.baeldung.gradle" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") + testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.9.0") +} + +tasks.getByName("test") { + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/provider2/build.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/provider2/build.gradle.kts new file mode 100644 index 0000000000..d3dcd96b08 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/provider2/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("java") +} + +group = "com.baeldung.gradle" +version = "0.0.1-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") + testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.9.0") +} + +tasks.getByName("test") { + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/settings.gradle.kts b/gradle-modules/gradle-7/conditional-dependency-demo/settings.gradle.kts new file mode 100644 index 0000000000..b6a25cf09d --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/settings.gradle.kts @@ -0,0 +1,5 @@ +rootProject.name = "conditional-dependency-demo" +include("provider1") +include("provider2") +include("consumer1") +include("consumer2") diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/src/main/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplication.java b/gradle-modules/gradle-7/conditional-dependency-demo/src/main/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplication.java new file mode 100644 index 0000000000..7921b72143 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/src/main/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.gradle.conditionaldependencydemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import java.util.Arrays; + +@SpringBootApplication +public class ConditionalDependencyDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(ConditionalDependencyDemoApplication.class, args); + } + +} diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/src/main/resources/application.properties b/gradle-modules/gradle-7/conditional-dependency-demo/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/gradle-modules/gradle-7/conditional-dependency-demo/src/test/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplicationTests.java b/gradle-modules/gradle-7/conditional-dependency-demo/src/test/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplicationTests.java new file mode 100644 index 0000000000..788dbd962a --- /dev/null +++ b/gradle-modules/gradle-7/conditional-dependency-demo/src/test/java/com/baeldung/gradle/conditionaldependencydemo/ConditionalDependencyDemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.baeldung.gradle.conditionaldependencydemo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ConditionalDependencyDemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/gradle-modules/settings.gradle b/gradle-modules/settings.gradle index f6e0614a10..34dbd0cf53 100644 --- a/gradle-modules/settings.gradle +++ b/gradle-modules/settings.gradle @@ -2,3 +2,4 @@ rootProject.name = 'gradle-modules' include 'gradle' include 'gradle-5' include 'gradle-6' +include 'gradle-7' From cdb19ff6d59fd2df38c34bffd2c768256b52000e Mon Sep 17 00:00:00 2001 From: Keerthi Date: Mon, 8 Aug 2022 23:26:55 +1000 Subject: [PATCH 37/39] JAVA-12045 : move java concurrency ebook content code to common module (#12559) * JAVA-12045 : move java concurrency ebook content code to common module * JAVA-12045: addressed the review comments .. renamed package names and placed core-java-concurrency-simple module in pom.xml * JAVA-12045: removed duplicate module after renaming java-simple-module to core-java-simple-module --- .../README.md | 1 - .../core-java-concurrency-advanced/README.md | 1 - .../core-java-concurrency-basic-2/README.md | 3 --- .../core-java-concurrency-basic/README.md | 3 --- .../core-java-concurrency-simple/README.md | 18 +++++++++++++ .../core-java-concurrency-simple/pom.xml | 26 +++++++++++++++++++ .../ScheduledExecutorServiceDemo.java | 0 .../daemon/MultipleThreadsExample.java | 0 .../baeldung/concurrent/daemon/NewThread.java | 0 .../daemon/SingleThreadExample.java | 0 .../executorservice/DelayedCallable.java | 0 .../executorservice/ExecutorServiceDemo.java | 0 .../concurrent/executorservice/Task.java | 0 .../BaeldungSynchronizedBlocks.java | 0 .../BaeldungSynchronizedMethods.java | 0 .../threadlifecycle/BlockedState.java | 0 .../concurrent/threadlifecycle/NewState.java | 0 .../threadlifecycle/RunnableState.java | 0 .../threadlifecycle/TerminatedState.java | 0 .../threadlifecycle/TimedWaitingState.java | 0 .../threadlifecycle/WaitingState.java | 0 .../volatilekeyword/SharedObject.java | 0 .../volatilekeyword/TaskRunner.java | 0 .../concurrent/waitandnotify/Data.java | 0 .../waitandnotify/NetworkDriver.java | 0 .../concurrent/waitandnotify/Receiver.java | 0 .../concurrent/waitandnotify/Sender.java | 0 .../CompletableFutureLongRunningUnitTest.java | 0 .../Java8ExecutorServiceIntegrationTest.java | 0 .../WaitingForThreadsToFinishManualTest.java | 0 .../BaeldungSychronizedBlockUnitTest.java | 0 .../BaeldungSynchronizeMethodsUnitTest.java | 0 .../SharedObjectManualTest.java | 0 .../waitandnotify/NetworkIntegrationTest.java | 0 .../thread/join/ThreadJoinUnitTest.java | 0 core-java-modules/pom.xml | 1 + 36 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 core-java-modules/core-java-concurrency-simple/README.md create mode 100644 core-java-modules/core-java-concurrency-simple/pom.xml rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/daemon/NewThread.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/executorservice/Task.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/executorservice/Java8ExecutorServiceIntegrationTest.java (100%) rename core-java-modules/{core-java-concurrency-basic => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java (100%) rename core-java-modules/{core-java-concurrency-advanced => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java (100%) rename core-java-modules/{core-java-concurrency-basic-2 => core-java-concurrency-simple}/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java (100%) rename core-java-modules/{core-java-concurrency-advanced-2 => core-java-concurrency-simple}/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java (100%) diff --git a/core-java-modules/core-java-concurrency-advanced-2/README.md b/core-java-modules/core-java-concurrency-advanced-2/README.md index 0e3d25689f..ca3ab715ea 100644 --- a/core-java-modules/core-java-concurrency-advanced-2/README.md +++ b/core-java-modules/core-java-concurrency-advanced-2/README.md @@ -11,7 +11,6 @@ This module contains articles about advanced topics about multithreading with co - [Java CyclicBarrier vs CountDownLatch](https://www.baeldung.com/java-cyclicbarrier-countdownlatch) - [Guide to the Fork/Join Framework in Java](https://www.baeldung.com/java-fork-join) - [Guide to ThreadLocalRandom in Java](https://www.baeldung.com/java-thread-local-random) -- [The Thread.join() Method in Java](https://www.baeldung.com/java-thread-join) - [Passing Parameters to Java Threads](https://www.baeldung.com/java-thread-parameters) [[<-- previous]](/core-java-modules/core-java-concurrency-advanced)[[next -->]](/core-java-modules/core-java-concurrency-advanced-3) diff --git a/core-java-modules/core-java-concurrency-advanced/README.md b/core-java-modules/core-java-concurrency-advanced/README.md index 0da59c88fb..947ed15e9e 100644 --- a/core-java-modules/core-java-concurrency-advanced/README.md +++ b/core-java-modules/core-java-concurrency-advanced/README.md @@ -12,5 +12,4 @@ This module contains articles about advanced topics about multithreading with co - [Guide to the Java Phaser](https://www.baeldung.com/java-phaser) - [An Introduction to Atomic Variables in Java](https://www.baeldung.com/java-atomic-variables) - [CyclicBarrier in Java](https://www.baeldung.com/java-cyclic-barrier) -- [Guide to the Volatile Keyword in Java](https://www.baeldung.com/java-volatile) - More Articles: [[next -->]](/core-java-modules/core-java-concurrency-advanced-2) diff --git a/core-java-modules/core-java-concurrency-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md index af46046709..c9f1c11a89 100644 --- a/core-java-modules/core-java-concurrency-basic-2/README.md +++ b/core-java-modules/core-java-concurrency-basic-2/README.md @@ -5,10 +5,7 @@ This module contains articles about basic Java concurrency ### Relevant Articles: - [How to Delay Code Execution in Java](https://www.baeldung.com/java-delay-code-execution) -- [wait and notify() Methods in Java](https://www.baeldung.com/java-wait-notify) - [Difference Between Wait and Sleep in Java](https://www.baeldung.com/java-wait-and-sleep) -- [Guide to the Synchronized Keyword in Java](https://www.baeldung.com/java-synchronized) -- [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) - [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference) - [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe) - [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time) diff --git a/core-java-modules/core-java-concurrency-basic/README.md b/core-java-modules/core-java-concurrency-basic/README.md index 846687b8dd..f1aa748c6b 100644 --- a/core-java-modules/core-java-concurrency-basic/README.md +++ b/core-java-modules/core-java-concurrency-basic/README.md @@ -3,8 +3,6 @@ This module contains articles about basic Java concurrency ### Relevant Articles: -- [Guide To CompletableFuture](https://www.baeldung.com/java-completablefuture) -- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial) - [Guide to java.util.concurrent.Future](https://www.baeldung.com/java-future) - [Overview of the java.util.concurrent](https://www.baeldung.com/java-util-concurrent) - [Implementing a Runnable vs Extending a Thread](https://www.baeldung.com/java-runnable-vs-extending-thread) @@ -12,5 +10,4 @@ This module contains articles about basic Java concurrency - [ExecutorService – Waiting for Threads to Finish](https://www.baeldung.com/java-executor-wait-for-threads) - [Runnable vs. Callable in Java](https://www.baeldung.com/java-runnable-callable) - [What is Thread-Safety and How to Achieve it?](https://www.baeldung.com/java-thread-safety) -- [How to Start a Thread in Java](https://www.baeldung.com/java-start-thread) - [[Next -->]](/core-java-modules/core-java-concurrency-basic-2) diff --git a/core-java-modules/core-java-concurrency-simple/README.md b/core-java-modules/core-java-concurrency-simple/README.md new file mode 100644 index 0000000000..861d9e7792 --- /dev/null +++ b/core-java-modules/core-java-concurrency-simple/README.md @@ -0,0 +1,18 @@ +### Mockito Articles that are also part of the e-book + +This module contains articles about Java Concurrency that are also part of an Ebook. + +## Relevant articles: + +- [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) +- [How to Start a Thread in Java](https://www.baeldung.com/java-start-thread) +- [Thread's wait and notify() Methods in Java](https://www.baeldung.com/java-wait-notify) +- [The Thread.join() Method in Java](https://www.baeldung.com/java-thread-join) +- [Guide to the Synchronized Keyword in Java](https://www.baeldung.com/java-synchronized) +- [Guide to the Volatile Keyword in Java](https://www.baeldung.com/java-volatile) +- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial) +- [Guide To CompletableFuture](https://www.baeldung.com/java-completablefuture) + +### NOTE: + +Since this is a module tied to an e-book, it should **not** be moved or used to store the code for any further article. diff --git a/core-java-modules/core-java-concurrency-simple/pom.xml b/core-java-modules/core-java-concurrency-simple/pom.xml new file mode 100644 index 0000000000..153d76d0d5 --- /dev/null +++ b/core-java-modules/core-java-concurrency-simple/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + java-concurrency-simple + 0.1.0-SNAPSHOT + java-concurrency-simple + jar + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + + + + java-concurrency-simple + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/NewThread.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/NewThread.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/Task.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/Task.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java b/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java rename to core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java diff --git a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java diff --git a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/Java8ExecutorServiceIntegrationTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/Java8ExecutorServiceIntegrationTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/Java8ExecutorServiceIntegrationTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/Java8ExecutorServiceIntegrationTest.java diff --git a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java diff --git a/core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java similarity index 100% rename from core-java-modules/core-java-concurrency-advanced-2/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java rename to core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index c650f064ab..981374a4ef 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -42,6 +42,7 @@ core-java-collections-maps-2 core-java-collections-maps-3 core-java-collections-maps-5 + core-java-concurrency-simple core-java-concurrency-2 core-java-concurrency-advanced core-java-concurrency-advanced-2 From 205aae4d4f5f7057a9daed448cd38faf275dd5e7 Mon Sep 17 00:00:00 2001 From: freelansam <79205526+freelansam@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:10:32 +0530 Subject: [PATCH 38/39] JAVA-13736: Fix maven-generate-war parent (#12575) --- maven-modules/maven-generate-war/pom.xml | 21 ++++++++++++++----- ...ationTests.java => SpringContextTest.java} | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) rename maven-modules/maven-generate-war/src/test/java/com/baeldung/{MavenGenerateWarApplicationTests.java => SpringContextTest.java} (81%) diff --git a/maven-modules/maven-generate-war/pom.xml b/maven-modules/maven-generate-war/pom.xml index 51eb54846c..cf8952e72f 100644 --- a/maven-modules/maven-generate-war/pom.xml +++ b/maven-modules/maven-generate-war/pom.xml @@ -11,11 +11,10 @@ Spring boot project to demonstrate war file generation - org.springframework.boot - spring-boot-starter-parent - 2.5.4 - - + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 @@ -58,12 +57,24 @@ + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + 11 2.17.1 + 3.10.1 + 11 + 11
\ No newline at end of file diff --git a/maven-modules/maven-generate-war/src/test/java/com/baeldung/MavenGenerateWarApplicationTests.java b/maven-modules/maven-generate-war/src/test/java/com/baeldung/SpringContextTest.java similarity index 81% rename from maven-modules/maven-generate-war/src/test/java/com/baeldung/MavenGenerateWarApplicationTests.java rename to maven-modules/maven-generate-war/src/test/java/com/baeldung/SpringContextTest.java index 71f4908d38..e8be16fd3a 100644 --- a/maven-modules/maven-generate-war/src/test/java/com/baeldung/MavenGenerateWarApplicationTests.java +++ b/maven-modules/maven-generate-war/src/test/java/com/baeldung/SpringContextTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest -class MavenGenerateWarApplicationTests { +class SpringContextTest { @Test void contextLoads() { From 8e74927325166e746a29381f8852631318b6e3e5 Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Mon, 8 Aug 2022 19:25:28 +0530 Subject: [PATCH 39/39] JAVA-13132 Cleaned persistence-modules sub-modules poms (#12553) * JAVA-13132 Cleaned persistence-modules sub-modules poms * JAVA-13132 Moved testcontainers.version property up * JAVA-13132 Update java-jpa-3 pom --- persistence-modules/apache-derby/pom.xml | 9 +++++++-- persistence-modules/core-java-persistence-2/pom.xml | 6 ++++-- persistence-modules/fauna/pom.xml | 3 ++- persistence-modules/hibernate-annotations/pom.xml | 2 -- persistence-modules/hibernate-enterprise/pom.xml | 1 - persistence-modules/java-jpa-3/pom.xml | 2 +- persistence-modules/java-mongodb-2/pom.xml | 4 ++-- persistence-modules/java-mongodb-queries/pom.xml | 6 ++++-- persistence-modules/java-mongodb/pom.xml | 4 ++-- persistence-modules/pom.xml | 2 ++ persistence-modules/querydsl/pom.xml | 1 - persistence-modules/spring-hibernate-5/pom.xml | 1 - 12 files changed, 24 insertions(+), 17 deletions(-) diff --git a/persistence-modules/apache-derby/pom.xml b/persistence-modules/apache-derby/pom.xml index f7f5ca7503..98901b5d80 100644 --- a/persistence-modules/apache-derby/pom.xml +++ b/persistence-modules/apache-derby/pom.xml @@ -16,14 +16,19 @@ org.apache.derby derby - 10.13.1.1 + ${derby.version} org.apache.derby derbyclient - 10.13.1.1 + ${derbyclient.version} + + 10.13.1.1 + 10.13.1.1 + + \ No newline at end of file diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml index d6109d2ae9..1d9852ae53 100644 --- a/persistence-modules/core-java-persistence-2/pom.xml +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -44,12 +44,12 @@ org.jooq jooq - 3.11.11 + ${jooq.version} org.json json - 20220320 + ${json.version} @@ -57,6 +57,8 @@ 8.4.1.jre11 10.2.0.4.0 8.0.22 + 3.11.11 + 20220320 \ No newline at end of file diff --git a/persistence-modules/fauna/pom.xml b/persistence-modules/fauna/pom.xml index a00dd0eb8d..90fa596406 100644 --- a/persistence-modules/fauna/pom.xml +++ b/persistence-modules/fauna/pom.xml @@ -26,7 +26,7 @@ com.faunadb faunadb-java - 4.2.0 + ${faunadb.version} compile @@ -60,6 +60,7 @@ 17 3.17.0 + 4.2.0 \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml index e984078f9a..6c02b6c685 100644 --- a/persistence-modules/hibernate-annotations/pom.xml +++ b/persistence-modules/hibernate-annotations/pom.xml @@ -84,10 +84,8 @@ 1.10.6.RELEASE 5.6.7.Final true - 2.1.7.RELEASE 2.1.212 9.0.0.M26 - 2.3.4 \ No newline at end of file diff --git a/persistence-modules/hibernate-enterprise/pom.xml b/persistence-modules/hibernate-enterprise/pom.xml index 18d1a4f3a6..833f19c673 100644 --- a/persistence-modules/hibernate-enterprise/pom.xml +++ b/persistence-modules/hibernate-enterprise/pom.xml @@ -82,7 +82,6 @@ 6.0.6 2.2.3 0.9 - 2.3.4 \ No newline at end of file diff --git a/persistence-modules/java-jpa-3/pom.xml b/persistence-modules/java-jpa-3/pom.xml index b67b8bf608..c6930d6291 100644 --- a/persistence-modules/java-jpa-3/pom.xml +++ b/persistence-modules/java-jpa-3/pom.xml @@ -65,7 +65,7 @@ org.testcontainers postgresql - 1.16.0 + ${testcontainers.version} test diff --git a/persistence-modules/java-mongodb-2/pom.xml b/persistence-modules/java-mongodb-2/pom.xml index 9475a86bee..cabe544850 100644 --- a/persistence-modules/java-mongodb-2/pom.xml +++ b/persistence-modules/java-mongodb-2/pom.xml @@ -33,13 +33,13 @@ org.testcontainers mongodb - 1.16.3 + ${testcontainers.version} test org.testcontainers junit-jupiter - 1.16.3 + ${testcontainers.version} test diff --git a/persistence-modules/java-mongodb-queries/pom.xml b/persistence-modules/java-mongodb-queries/pom.xml index aa3003bef6..8293103859 100644 --- a/persistence-modules/java-mongodb-queries/pom.xml +++ b/persistence-modules/java-mongodb-queries/pom.xml @@ -16,12 +16,12 @@ org.mongodb mongodb-driver-sync - 4.6.0 + ${mongodb.version} org.junit.jupiter junit-jupiter-api - 5.8.1 + ${junit.version} compile @@ -29,6 +29,8 @@ 8 8 + 4.6.0 + 5.8.1 \ No newline at end of file diff --git a/persistence-modules/java-mongodb/pom.xml b/persistence-modules/java-mongodb/pom.xml index 88f0d18a5b..2e366d8368 100644 --- a/persistence-modules/java-mongodb/pom.xml +++ b/persistence-modules/java-mongodb/pom.xml @@ -33,13 +33,13 @@ org.testcontainers mongodb - 1.16.3 + ${testcontainers.version} test org.testcontainers junit-jupiter - 1.16.3 + ${testcontainers.version} test diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index ee4807933a..d549f7e2de 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -111,6 +111,8 @@ 5.2.17.Final 42.2.20 + 2.3.4 + 1.16.3 \ No newline at end of file diff --git a/persistence-modules/querydsl/pom.xml b/persistence-modules/querydsl/pom.xml index c4b01d787c..c97dcdd93d 100644 --- a/persistence-modules/querydsl/pom.xml +++ b/persistence-modules/querydsl/pom.xml @@ -136,7 +136,6 @@ 5.2.5.Final 1.0.0.Final 4.1.4 - 2.3.4 1.6 1.4 1.1.3 diff --git a/persistence-modules/spring-hibernate-5/pom.xml b/persistence-modules/spring-hibernate-5/pom.xml index 3f5d00733d..e559fe1394 100644 --- a/persistence-modules/spring-hibernate-5/pom.xml +++ b/persistence-modules/spring-hibernate-5/pom.xml @@ -136,7 +136,6 @@ 8.0.7-dmr 9.0.0.M26 1.1 - 2.3.4 2.3.0.1 2.3.1