From 3a4cddb740638446496efc906e2d71d2b0d74c4a Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sat, 19 Aug 2017 20:41:55 +0100 Subject: [PATCH 01/36] Different types of bean injection in Spring --- pom.xml | 1 + spring-types-bean-injection/README.md | 3 + spring-types-bean-injection/pom.xml | 81 +++++++++++++++++++ .../java/com/baeldung/config/AppConfig.java | 25 ++++++ .../com/baeldung/service/MegaTestService.java | 22 +++++ .../baeldung/service/SuperTestService.java | 22 +++++ .../com/baeldung/service/TestService.java | 14 ++++ .../MegaTestServiceIntegrationTest.java | 32 ++++++++ .../SuperTestServiceIntegrationTest.java | 32 ++++++++ .../service/TestServiceIntegrationTest.java | 32 ++++++++ 10 files changed, 264 insertions(+) create mode 100644 spring-types-bean-injection/README.md create mode 100644 spring-types-bean-injection/pom.xml create mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java create mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java create mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java create mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java create mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java create mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java create mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java diff --git a/pom.xml b/pom.xml index b76c9b8ddd..eef32f884e 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,7 @@ spring-social-login spring-spel spring-thymeleaf + spring-types-bean-injection spring-userservice spring-zuul spring-reactor diff --git a/spring-types-bean-injection/README.md b/spring-types-bean-injection/README.md new file mode 100644 index 0000000000..45f8216849 --- /dev/null +++ b/spring-types-bean-injection/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Constructor Dependency Injection in Spring](http://www.baeldung.com/constructor-injection-in-spring) \ No newline at end of file diff --git a/spring-types-bean-injection/pom.xml b/spring-types-bean-injection/pom.xml new file mode 100644 index 0000000000..75fee65d80 --- /dev/null +++ b/spring-types-bean-injection/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + com.baeldung + spring-types-bean-injection + 0.0.1-SNAPSHOT + jar + + spring-types-bean-injection + Types of bean injection in spring + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + test + + + junit + junit + ${junit.version} + test + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + + + 1.8 + 4.3.10.RELEASE + 4.12 + + + diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java b/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java new file mode 100644 index 0000000000..45be32fa06 --- /dev/null +++ b/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java @@ -0,0 +1,25 @@ +package com.baeldung.config; + +import com.baeldung.service.MegaTestService; +import com.baeldung.service.SuperTestService; +import com.baeldung.service.TestService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfig { + @Bean + public TestService TestService() { + return new TestService(); + } + + @Bean + public SuperTestService SuperTestService() { + return new SuperTestService(new TestService()); + } + + @Bean + public MegaTestService MegaTestService() { + return new MegaTestService(); + } +} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java new file mode 100644 index 0000000000..45deeb8592 --- /dev/null +++ b/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java @@ -0,0 +1,22 @@ +package com.baeldung.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MegaTestService { + private TestService testService; + + @Autowired + public void setTestService(TestService testService) { + this.testService = testService; + } + + public String getMegaTestOne() { + return "Mega" + testService.getTestOne(); + } + + public String getMegaTestTwo() { + return "Mega" + testService.getTestTwo(); + } +} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java new file mode 100644 index 0000000000..edf1f2b1c5 --- /dev/null +++ b/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java @@ -0,0 +1,22 @@ +package com.baeldung.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SuperTestService { + private TestService testService; + + @Autowired + public SuperTestService(TestService testService) { + this.testService = testService; + } + + public String getSuperTestOne() { + return "Super" + testService.getTestOne(); + } + + public String getSuperTestTwo() { + return "Super" + testService.getTestTwo(); + } +} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java new file mode 100644 index 0000000000..3e7c327dbd --- /dev/null +++ b/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java @@ -0,0 +1,14 @@ +package com.baeldung.service; + +import org.springframework.stereotype.Service; + +@Service +public class TestService { + public String getTestOne() { + return "TestOne"; + } + + public String getTestTwo() { + return "TestTwo"; + } +} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java new file mode 100644 index 0000000000..ced897c70c --- /dev/null +++ b/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.service; + +import com.baeldung.config.AppConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.CoreMatchers.is; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {AppConfig.class}) +public class MegaTestServiceIntegrationTest { + @Autowired + MegaTestService megaTestService; + + @Test + public void whenCallingGetMegaTestOne_thenWeGetMegaTestOneString() { + String resultOne = megaTestService.getMegaTestOne(); + + Assert.assertThat(resultOne, is("MegaTestOne")); + } + + @Test + public void whenCallingGetMegaTestTwo_thenWeGetMegaTestTwoString() { + String resultTwo = megaTestService.getMegaTestTwo(); + + Assert.assertThat(resultTwo, is("MegaTestTwo")); + } +} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java new file mode 100644 index 0000000000..a037d70c40 --- /dev/null +++ b/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.service; + +import com.baeldung.config.AppConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.CoreMatchers.is; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {AppConfig.class}) +public class SuperTestServiceIntegrationTest { + @Autowired + SuperTestService superTestService; + + @Test + public void whenCallingGetSuperTestOne_thenWeGetSuperTestOneString() { + String resultOne = superTestService.getSuperTestOne(); + + Assert.assertThat(resultOne, is("SuperTestOne")); + } + + @Test + public void whenCallingGetSuperTestTwo_thenWeGetSuperTestTwoString() { + String resultTwo = superTestService.getSuperTestTwo(); + + Assert.assertThat(resultTwo, is("SuperTestTwo")); + } +} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java new file mode 100644 index 0000000000..2059e87e04 --- /dev/null +++ b/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.service; + +import com.baeldung.config.AppConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.CoreMatchers.is; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { AppConfig.class }) +public class TestServiceIntegrationTest { + @Autowired + TestService testService; + + @Test + public void whenCallingGetTestOne_thenWeGetTestOneString() { + String resultOne = testService.getTestOne(); + + Assert.assertThat(resultOne, is("TestOne")); + } + + @Test + public void whenCallingGetTestTwo_thenWeGetTestTwoString() { + String resultTwo = testService.getTestTwo(); + + Assert.assertThat(resultTwo, is("TestTwo")); + } +} \ No newline at end of file From 28bb7fc8d3ed564e3260d339a830797d09b7bb51 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 24 Aug 2017 21:04:23 +0100 Subject: [PATCH 02/36] Difference between two dates in java --- java-difference-date/README.md | 3 + java-difference-date/pom.xml | 58 ++++++++++++++++++ .../src/main/java/com/baeldung/DateDiff.java | 30 ++++++++++ .../test/java/com/baeldung/DateDiffTest.java | 60 +++++++++++++++++++ pom.xml | 1 + 5 files changed, 152 insertions(+) create mode 100644 java-difference-date/README.md create mode 100644 java-difference-date/pom.xml create mode 100644 java-difference-date/src/main/java/com/baeldung/DateDiff.java create mode 100644 java-difference-date/src/test/java/com/baeldung/DateDiffTest.java diff --git a/java-difference-date/README.md b/java-difference-date/README.md new file mode 100644 index 0000000000..45f8216849 --- /dev/null +++ b/java-difference-date/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Constructor Dependency Injection in Spring](http://www.baeldung.com/constructor-injection-in-spring) \ No newline at end of file diff --git a/java-difference-date/pom.xml b/java-difference-date/pom.xml new file mode 100644 index 0000000000..388753de90 --- /dev/null +++ b/java-difference-date/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.baeldung + java-difference-date + 0.0.1-SNAPSHOT + jar + + java-difference-date + Difference between two dates in java + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + joda-time + joda-time + ${joda-time.version} + + + com.darwinsys + hirondelle-date4j + ${hirondelle-date4j.version} + + + junit + junit + ${junit.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + 1.8 + 4.12 + 2.9.9 + 1.5.1 + + diff --git a/java-difference-date/src/main/java/com/baeldung/DateDiff.java b/java-difference-date/src/main/java/com/baeldung/DateDiff.java new file mode 100644 index 0000000000..08fc02fab7 --- /dev/null +++ b/java-difference-date/src/main/java/com/baeldung/DateDiff.java @@ -0,0 +1,30 @@ +package com.baeldung; + +import org.joda.time.DateTime; + +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public class DateDiff { + public long beforeJava8diff(Date firstDate, Date secondDate){ + long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime()); + return TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS); + } + + public long fromJava8Diff(ZonedDateTime firstDate, ZonedDateTime secondDate){ + Duration duration = Duration.between(firstDate, secondDate); + return Math.abs(duration.toDays()); + } + + public long fromJodaTime(DateTime firstDate, DateTime secondDate){ + org.joda.time.Duration duration = new org.joda.time.Duration(firstDate, secondDate); + return Math.abs(duration.getStandardDays()); + } + + public long fromDate4j(hirondelle.date4j.DateTime firstDate, hirondelle.date4j.DateTime secondDate){ + long diff = firstDate.numDaysFrom(secondDate); + return Math.abs(diff); + } +} \ No newline at end of file diff --git a/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java new file mode 100644 index 0000000000..fe2b507cf3 --- /dev/null +++ b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java @@ -0,0 +1,60 @@ +package com.baeldung; + +import org.joda.time.DateTime; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import static org.junit.Assert.assertEquals; + +public class DateDiffTest { + @Test + public void givenTwoDatesBeforeJava8SeparatedBySixDays_whenCallingDiffOnThem_thenWeGetSix() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH); + Date firstDate = sdf.parse("06/24/2017"); + Date secondDate = sdf.parse("06/30/2017"); + + DateDiff dateDiff = new DateDiff(); + long diff = dateDiff.beforeJava8diff(firstDate, secondDate); + + assertEquals(diff, 6); + } + + @Test + public void givenTheCurrentDateAndSixDaysBehindInJava8_whenCallingDiffOnThem_thenWeGetSix() { + ZonedDateTime now = ZonedDateTime.now(); + ZonedDateTime sixDaysBehind = now.minusDays(6); + + DateDiff dateDiff = new DateDiff(); + long diff = dateDiff.fromJava8Diff(now, sixDaysBehind); + + assertEquals(diff, 6); + } + + @Test + public void givenTheCurrentDateAndSixDaysBehindInJodaTime_whenCallingDiffOnThem_thenWeGetSix() { + DateTime now = DateTime.now(); + DateTime sixDaysBehind = now.minusDays(6); + + DateDiff dateDiff = new DateDiff(); + long diff = dateDiff.fromJodaTime(now, sixDaysBehind); + + assertEquals(diff, 6); + } + + @Test + public void givenTheCurrentDateAndSixDaysBehindInDate4j_whenCallingDiffOnThem_thenWeGetSix() { + hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault()); + hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6); + + DateDiff dateDiff = new DateDiff(); + long diff = dateDiff.fromDate4j(now, sixDaysBehind); + + assertEquals(diff, 6); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index eef32f884e..d2d9ae3987 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,7 @@ immutables jackson + java-difference-date java-cassandra javaslang javax-servlets From 348ff5d403c3ebae00ea8ef7e5a681d1cdb5cb03 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 24 Aug 2017 21:36:52 +0100 Subject: [PATCH 03/36] Update README.md --- java-difference-date/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java-difference-date/README.md b/java-difference-date/README.md index 45f8216849..2a024c27a2 100644 --- a/java-difference-date/README.md +++ b/java-difference-date/README.md @@ -1,3 +1,5 @@ ## Relevant articles: -- [Constructor Dependency Injection in Spring](http://www.baeldung.com/constructor-injection-in-spring) \ No newline at end of file +- [Period and Duration in Java](http://www.baeldung.com/java-period-duration) +- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro) +- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api) \ No newline at end of file From a663b3ccde9fdbab1c8d2f8f3e0d13d11294b0d8 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Fri, 25 Aug 2017 09:46:35 +0100 Subject: [PATCH 04/36] Simple clean of difference between dates --- core-java/README.md | 3 + core-java/pom.xml | 14 ++++- .../java/com/baeldung/DateDiffUnitTest.java | 63 +++++++++++++++++++ .../src/main/java/com/baeldung/DateDiff.java | 30 --------- .../test/java/com/baeldung/DateDiffTest.java | 25 ++++---- pom.xml | 1 - 6 files changed, 92 insertions(+), 44 deletions(-) create mode 100644 core-java/src/test/java/com/baeldung/DateDiffUnitTest.java delete mode 100644 java-difference-date/src/main/java/com/baeldung/DateDiff.java diff --git a/core-java/README.md b/core-java/README.md index dabf6f39be..a4b5127e98 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -141,3 +141,6 @@ - [Guide to UUID in Java](http://www.baeldung.com/java-uuid) - [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element) - [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char) +- [Period and Duration in Java](http://www.baeldung.com/java-period-duration) +- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro) +- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api) diff --git a/core-java/pom.xml b/core-java/pom.xml index 422965a0ed..586486027a 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -186,6 +186,16 @@ fscontext ${fscontext.version} + + joda-time + joda-time + ${joda-time.version} + + + com.darwinsys + hirondelle-date4j + ${hirondelle-date4j.version} + @@ -408,6 +418,8 @@ 1.8.7 1.16.12 4.6-b01 + 2.9.9 + 1.5.1 1.3 @@ -416,9 +428,9 @@ 3.6.1 1.7.0 + 3.6.0 2.19.1 - diff --git a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java new file mode 100644 index 0000000000..40b7fac30d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung; + +import org.joda.time.DateTime; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; + +public class DateDiffUnitTest { + + @Test + public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH); + Date firstDate = sdf.parse("06/24/2017"); + Date secondDate = sdf.parse("06/30/2017"); + + long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime()); + long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS); + + assertEquals(diff, 6); + } + + @Test + public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() { + ZonedDateTime now = ZonedDateTime.now(); + ZonedDateTime sixDaysBehind = now.minusDays(6); + + Duration duration = Duration.between(now, sixDaysBehind); + long diff = Math.abs(duration.toDays()); + + assertEquals(diff, 6); + } + + @Test + public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() { + DateTime now = DateTime.now(); + DateTime sixDaysBehind = now.minusDays(6); + + org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind); + long diff = Math.abs(duration.getStandardDays()); + + assertEquals(diff, 6); + } + + @Test + public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() { + hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault()); + hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6); + + long diff = Math.abs(now.numDaysFrom(sixDaysBehind)); + + assertEquals(diff, 6); + } + +} \ No newline at end of file diff --git a/java-difference-date/src/main/java/com/baeldung/DateDiff.java b/java-difference-date/src/main/java/com/baeldung/DateDiff.java deleted file mode 100644 index 08fc02fab7..0000000000 --- a/java-difference-date/src/main/java/com/baeldung/DateDiff.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung; - -import org.joda.time.DateTime; - -import java.time.Duration; -import java.time.ZonedDateTime; -import java.util.Date; -import java.util.concurrent.TimeUnit; - -public class DateDiff { - public long beforeJava8diff(Date firstDate, Date secondDate){ - long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime()); - return TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS); - } - - public long fromJava8Diff(ZonedDateTime firstDate, ZonedDateTime secondDate){ - Duration duration = Duration.between(firstDate, secondDate); - return Math.abs(duration.toDays()); - } - - public long fromJodaTime(DateTime firstDate, DateTime secondDate){ - org.joda.time.Duration duration = new org.joda.time.Duration(firstDate, secondDate); - return Math.abs(duration.getStandardDays()); - } - - public long fromDate4j(hirondelle.date4j.DateTime firstDate, hirondelle.date4j.DateTime secondDate){ - long diff = firstDate.numDaysFrom(secondDate); - return Math.abs(diff); - } -} \ No newline at end of file diff --git a/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java index fe2b507cf3..4203f7ef38 100644 --- a/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java +++ b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java @@ -5,55 +5,56 @@ import org.junit.Test; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.Duration; import java.time.ZonedDateTime; import java.util.Date; import java.util.Locale; import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; public class DateDiffTest { @Test - public void givenTwoDatesBeforeJava8SeparatedBySixDays_whenCallingDiffOnThem_thenWeGetSix() throws ParseException { + public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH); Date firstDate = sdf.parse("06/24/2017"); Date secondDate = sdf.parse("06/30/2017"); - DateDiff dateDiff = new DateDiff(); - long diff = dateDiff.beforeJava8diff(firstDate, secondDate); + long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime()); + long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS); assertEquals(diff, 6); } @Test - public void givenTheCurrentDateAndSixDaysBehindInJava8_whenCallingDiffOnThem_thenWeGetSix() { + public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() { ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime sixDaysBehind = now.minusDays(6); - DateDiff dateDiff = new DateDiff(); - long diff = dateDiff.fromJava8Diff(now, sixDaysBehind); + Duration duration = Duration.between(now, sixDaysBehind); + long diff = Math.abs(duration.toDays()); assertEquals(diff, 6); } @Test - public void givenTheCurrentDateAndSixDaysBehindInJodaTime_whenCallingDiffOnThem_thenWeGetSix() { + public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() { DateTime now = DateTime.now(); DateTime sixDaysBehind = now.minusDays(6); - DateDiff dateDiff = new DateDiff(); - long diff = dateDiff.fromJodaTime(now, sixDaysBehind); + org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind); + long diff = Math.abs(duration.getStandardDays()); assertEquals(diff, 6); } @Test - public void givenTheCurrentDateAndSixDaysBehindInDate4j_whenCallingDiffOnThem_thenWeGetSix() { + public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() { hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault()); hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6); - DateDiff dateDiff = new DateDiff(); - long diff = dateDiff.fromDate4j(now, sixDaysBehind); + long diff = Math.abs(now.numDaysFrom(sixDaysBehind)); assertEquals(diff, 6); } diff --git a/pom.xml b/pom.xml index 40e7fda4a3..b5dee350ca 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,6 @@ immutables jackson - java-difference-date vavr javax-servlets From 4f827b93ed171cfa26035d8a9e7897489111abed Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Fri, 25 Aug 2017 12:36:28 +0100 Subject: [PATCH 05/36] Clean my test article --- pom.xml | 1 - spring-types-bean-injection/README.md | 3 - spring-types-bean-injection/pom.xml | 81 ------------------- .../java/com/baeldung/config/AppConfig.java | 25 ------ .../com/baeldung/service/MegaTestService.java | 22 ----- .../baeldung/service/SuperTestService.java | 22 ----- .../com/baeldung/service/TestService.java | 14 ---- .../MegaTestServiceIntegrationTest.java | 32 -------- .../SuperTestServiceIntegrationTest.java | 32 -------- .../service/TestServiceIntegrationTest.java | 32 -------- 10 files changed, 264 deletions(-) delete mode 100644 spring-types-bean-injection/README.md delete mode 100644 spring-types-bean-injection/pom.xml delete mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java delete mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java delete mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java delete mode 100644 spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java delete mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java delete mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java delete mode 100644 spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java diff --git a/pom.xml b/pom.xml index b5dee350ca..f2dd0ae48c 100644 --- a/pom.xml +++ b/pom.xml @@ -212,7 +212,6 @@ spring-spel spring-state-machine spring-thymeleaf - spring-types-bean-injection spring-userservice spring-zuul spring-reactor diff --git a/spring-types-bean-injection/README.md b/spring-types-bean-injection/README.md deleted file mode 100644 index 45f8216849..0000000000 --- a/spring-types-bean-injection/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant articles: - -- [Constructor Dependency Injection in Spring](http://www.baeldung.com/constructor-injection-in-spring) \ No newline at end of file diff --git a/spring-types-bean-injection/pom.xml b/spring-types-bean-injection/pom.xml deleted file mode 100644 index 75fee65d80..0000000000 --- a/spring-types-bean-injection/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - 4.0.0 - - com.baeldung - spring-types-bean-injection - 0.0.1-SNAPSHOT - jar - - spring-types-bean-injection - Types of bean injection in spring - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.springframework - spring-context - ${spring.version} - - - org.springframework - spring-test - ${spring.version} - test - - - junit - junit - ${junit.version} - test - - - - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - - - **/*IntegrationTest.java - - - - - - - json - - - - - - - - - - 1.8 - 4.3.10.RELEASE - 4.12 - - - diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java b/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java deleted file mode 100644 index 45be32fa06..0000000000 --- a/spring-types-bean-injection/src/main/java/com/baeldung/config/AppConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.config; - -import com.baeldung.service.MegaTestService; -import com.baeldung.service.SuperTestService; -import com.baeldung.service.TestService; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class AppConfig { - @Bean - public TestService TestService() { - return new TestService(); - } - - @Bean - public SuperTestService SuperTestService() { - return new SuperTestService(new TestService()); - } - - @Bean - public MegaTestService MegaTestService() { - return new MegaTestService(); - } -} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java deleted file mode 100644 index 45deeb8592..0000000000 --- a/spring-types-bean-injection/src/main/java/com/baeldung/service/MegaTestService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class MegaTestService { - private TestService testService; - - @Autowired - public void setTestService(TestService testService) { - this.testService = testService; - } - - public String getMegaTestOne() { - return "Mega" + testService.getTestOne(); - } - - public String getMegaTestTwo() { - return "Mega" + testService.getTestTwo(); - } -} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java deleted file mode 100644 index edf1f2b1c5..0000000000 --- a/spring-types-bean-injection/src/main/java/com/baeldung/service/SuperTestService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class SuperTestService { - private TestService testService; - - @Autowired - public SuperTestService(TestService testService) { - this.testService = testService; - } - - public String getSuperTestOne() { - return "Super" + testService.getTestOne(); - } - - public String getSuperTestTwo() { - return "Super" + testService.getTestTwo(); - } -} diff --git a/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java b/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java deleted file mode 100644 index 3e7c327dbd..0000000000 --- a/spring-types-bean-injection/src/main/java/com/baeldung/service/TestService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.service; - -import org.springframework.stereotype.Service; - -@Service -public class TestService { - public String getTestOne() { - return "TestOne"; - } - - public String getTestTwo() { - return "TestTwo"; - } -} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java deleted file mode 100644 index ced897c70c..0000000000 --- a/spring-types-bean-injection/src/test/java/com/baeldung/service/MegaTestServiceIntegrationTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.service; - -import com.baeldung.config.AppConfig; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.hamcrest.CoreMatchers.is; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = {AppConfig.class}) -public class MegaTestServiceIntegrationTest { - @Autowired - MegaTestService megaTestService; - - @Test - public void whenCallingGetMegaTestOne_thenWeGetMegaTestOneString() { - String resultOne = megaTestService.getMegaTestOne(); - - Assert.assertThat(resultOne, is("MegaTestOne")); - } - - @Test - public void whenCallingGetMegaTestTwo_thenWeGetMegaTestTwoString() { - String resultTwo = megaTestService.getMegaTestTwo(); - - Assert.assertThat(resultTwo, is("MegaTestTwo")); - } -} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java deleted file mode 100644 index a037d70c40..0000000000 --- a/spring-types-bean-injection/src/test/java/com/baeldung/service/SuperTestServiceIntegrationTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.service; - -import com.baeldung.config.AppConfig; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.hamcrest.CoreMatchers.is; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = {AppConfig.class}) -public class SuperTestServiceIntegrationTest { - @Autowired - SuperTestService superTestService; - - @Test - public void whenCallingGetSuperTestOne_thenWeGetSuperTestOneString() { - String resultOne = superTestService.getSuperTestOne(); - - Assert.assertThat(resultOne, is("SuperTestOne")); - } - - @Test - public void whenCallingGetSuperTestTwo_thenWeGetSuperTestTwoString() { - String resultTwo = superTestService.getSuperTestTwo(); - - Assert.assertThat(resultTwo, is("SuperTestTwo")); - } -} diff --git a/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java b/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java deleted file mode 100644 index 2059e87e04..0000000000 --- a/spring-types-bean-injection/src/test/java/com/baeldung/service/TestServiceIntegrationTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.service; - -import com.baeldung.config.AppConfig; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.hamcrest.CoreMatchers.is; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = { AppConfig.class }) -public class TestServiceIntegrationTest { - @Autowired - TestService testService; - - @Test - public void whenCallingGetTestOne_thenWeGetTestOneString() { - String resultOne = testService.getTestOne(); - - Assert.assertThat(resultOne, is("TestOne")); - } - - @Test - public void whenCallingGetTestTwo_thenWeGetTestTwoString() { - String resultTwo = testService.getTestTwo(); - - Assert.assertThat(resultTwo, is("TestTwo")); - } -} \ No newline at end of file From c4fd005da4d41ea4efffecb8a0ac7b1a93d6cc8f Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Mon, 28 Aug 2017 05:23:07 +0100 Subject: [PATCH 06/36] Improve dates diff: for dates and datetimes --- .../java/com/baeldung/DateDiffUnitTest.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java index 40b7fac30d..ae9bae0050 100644 --- a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java +++ b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java @@ -1,12 +1,14 @@ package com.baeldung; import org.joda.time.DateTime; +import org.joda.time.Interval; import org.junit.Test; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Duration; -import java.time.ZonedDateTime; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Date; import java.util.Locale; import java.util.TimeZone; @@ -30,8 +32,8 @@ public class DateDiffUnitTest { @Test public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() { - ZonedDateTime now = ZonedDateTime.now(); - ZonedDateTime sixDaysBehind = now.minusDays(6); + LocalDate now = LocalDate.now(); + LocalDate sixDaysBehind = now.minusDays(6); Duration duration = Duration.between(now, sixDaysBehind); long diff = Math.abs(duration.toDays()); @@ -40,12 +42,34 @@ public class DateDiffUnitTest { } @Test - public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() { - DateTime now = DateTime.now(); - DateTime sixDaysBehind = now.minusDays(6); + public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime sixMinutesBehind = now.minusMinutes(6); - org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind); - long diff = Math.abs(duration.getStandardDays()); + Duration duration = Duration.between(now, sixMinutesBehind); + long diff = Math.abs(duration.toMinutes()); + + assertEquals(diff, 6); + } + + @Test + public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() { + org.joda.time.LocalDate now = org.joda.time.LocalDate.now(); + org.joda.time.LocalDate sixDaysBehind = now.minusDays(6); + + org.joda.time.Period period = new org.joda.time.Period(now, sixDaysBehind); + long diff = Math.abs(period.getDays()); + + assertEquals(diff, 6); + } + + @Test + public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() { + org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now(); + org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes(6); + + org.joda.time.Period period = new org.joda.time.Period(now, sixMinutesBehind); + long diff = Math.abs(period.getDays()); assertEquals(diff, 6); } From 82ed9489e51c85a7a623491c3be9d1090a2b4af0 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 30 Aug 2017 14:35:38 +0100 Subject: [PATCH 07/36] Move difference between dates from core-java to libraries --- core-java/pom.xml | 13 ------------- libraries/pom.xml | 18 ++++++++++++++++++ .../com/baeldung/date}/DateDiffUnitTest.java | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) rename {core-java/src/test/java/com/baeldung => libraries/src/test/java/com/baeldung/date}/DateDiffUnitTest.java (98%) diff --git a/core-java/pom.xml b/core-java/pom.xml index 586486027a..25029c237f 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -186,16 +186,6 @@ fscontext ${fscontext.version} - - joda-time - joda-time - ${joda-time.version} - - - com.darwinsys - hirondelle-date4j - ${hirondelle-date4j.version} - @@ -418,9 +408,6 @@ 1.8.7 1.16.12 4.6-b01 - 2.9.9 - 1.5.1 - 1.3 4.12 diff --git a/libraries/pom.xml b/libraries/pom.xml index 6d1098246e..ee92642b62 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -498,6 +498,22 @@ gt-swing ${geotools.version} + + com.darwinsys + hirondelle-date4j + RELEASE + test + + + joda-time + joda-time + ${joda-time.version} + + + com.darwinsys + hirondelle-date4j + ${hirondelle-date4j.version} + @@ -564,5 +580,7 @@ 0.6.5 0.9.0 15.2 + 2.9.9 + 1.5.1 \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java b/libraries/src/test/java/com/baeldung/date/DateDiffUnitTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/DateDiffUnitTest.java rename to libraries/src/test/java/com/baeldung/date/DateDiffUnitTest.java index 324a0d4587..6046781619 100644 --- a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java +++ b/libraries/src/test/java/com/baeldung/date/DateDiffUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.date; import org.junit.Test; From cccaa8c4ad6c65d7567a9ffad6f08acffb72ae89 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 7 Sep 2017 23:44:30 +0100 Subject: [PATCH 08/36] BAEL-890 - Kotlin-Allopen with Spring example --- spring-mvc-kotlin/pom.xml | 21 +++++++++++++++++-- .../kotlin/allopen/SimpleConfiguration.kt | 7 +++++++ .../kotlin/allopen/SimpleConfigurationTest.kt | 19 +++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt create mode 100644 spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt diff --git a/spring-mvc-kotlin/pom.xml b/spring-mvc-kotlin/pom.xml index 264cf49817..2d1dac5e29 100644 --- a/spring-mvc-kotlin/pom.xml +++ b/spring-mvc-kotlin/pom.xml @@ -45,6 +45,12 @@ thymeleaf-spring4 3.0.7.RELEASE + + org.springframework + spring-test + 4.3.10.RELEASE + test + @@ -55,7 +61,12 @@ kotlin-maven-plugin org.jetbrains.kotlin 1.1.4 - + + + spring + + 1.8 + compile @@ -64,7 +75,6 @@ compile - test-compile test-compile @@ -73,6 +83,13 @@ + + + org.jetbrains.kotlin + kotlin-maven-allopen + 1.1.4-3 + + diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt new file mode 100644 index 0000000000..5d0a3e13bf --- /dev/null +++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt @@ -0,0 +1,7 @@ +package com.baeldung.kotlin.allopen + +import org.springframework.context.annotation.Configuration + +@Configuration +class SimpleConfiguration { +} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt new file mode 100644 index 0000000000..65a60c7157 --- /dev/null +++ b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt @@ -0,0 +1,19 @@ +package com.baeldung.kotlin.allopen + +import org.junit.Test +import org.junit.runner.RunWith +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner +import org.springframework.test.context.support.AnnotationConfigContextLoader + +@RunWith(SpringJUnit4ClassRunner::class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader::class, + classes = arrayOf(SimpleConfiguration::class)) +class SimpleConfigurationTest { + + @Test + fun contextLoads() { + } + +} \ No newline at end of file From 28ad804484b59e7952566989f5284fa220595661 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 20 Sep 2017 07:01:45 +0100 Subject: [PATCH 09/36] BAEL-1107 - Introduction to Apache Cayenne Orm --- apache-cayenne/pom.xml | 59 ++++++++ .../apachecayenne/persistent/Article.java | 9 ++ .../apachecayenne/persistent/Author.java | 9 ++ .../persistent/auto/_Article.java | 47 ++++++ .../persistent/auto/_Author.java | 52 +++++++ .../src/main/resources/cayenne-project.xml | 17 +++ .../src/main/resources/datamap.map.xml | 34 +++++ .../apachecayenne/CayenneOperationTests.java | 140 ++++++++++++++++++ pom.xml | 1 + 9 files changed, 368 insertions(+) create mode 100644 apache-cayenne/pom.xml create mode 100644 apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Article.java create mode 100644 apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Author.java create mode 100644 apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Article.java create mode 100644 apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java create mode 100644 apache-cayenne/src/main/resources/cayenne-project.xml create mode 100644 apache-cayenne/src/main/resources/datamap.map.xml create mode 100644 apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java diff --git a/apache-cayenne/pom.xml b/apache-cayenne/pom.xml new file mode 100644 index 0000000000..23837d7019 --- /dev/null +++ b/apache-cayenne/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + apache-cayenne + 0.0.1-SNAPSHOT + jar + + apache-cayenne + Introduction to Apache Cayenne + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + 5.1.31 + 4.0.M5 + 4.12 + + + + + org.apache.cayenne + cayenne-server + ${cayenne.version} + + + mysql + mysql-connector-java + ${mysql.connector.version} + runtime + + + + junit + junit + ${junit.version} + test + + + + + + + org.apache.cayenne.plugins + cayenne-modeler-maven-plugin + ${cayenne.version} + + + + + diff --git a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Article.java b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Article.java new file mode 100644 index 0000000000..303c180887 --- /dev/null +++ b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Article.java @@ -0,0 +1,9 @@ +package com.baeldung.apachecayenne.persistent; + +import com.baeldung.apachecayenne.persistent.auto._Article; + +public class Article extends _Article { + + private static final long serialVersionUID = 1L; + +} diff --git a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Author.java b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Author.java new file mode 100644 index 0000000000..5a8df57c6e --- /dev/null +++ b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/Author.java @@ -0,0 +1,9 @@ +package com.baeldung.apachecayenne.persistent; + +import com.baeldung.apachecayenne.persistent.auto._Author; + +public class Author extends _Author { + + private static final long serialVersionUID = 1L; + +} diff --git a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Article.java b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Article.java new file mode 100644 index 0000000000..f6c179fcfd --- /dev/null +++ b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Article.java @@ -0,0 +1,47 @@ +package com.baeldung.apachecayenne.persistent.auto; + +import org.apache.cayenne.CayenneDataObject; +import org.apache.cayenne.exp.Property; + +import com.baeldung.apachecayenne.persistent.Author; + +/** + * Class _Article was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public abstract class _Article extends CayenneDataObject { + + private static final long serialVersionUID = 1L; + + public static final String ID_PK_COLUMN = "id"; + + public static final Property CONTENT = Property.create("content", String.class); + public static final Property TITLE = Property.create("title", String.class); + public static final Property AUTHOR = Property.create("author", Author.class); + + public void setContent(String content) { + writeProperty("content", content); + } + public String getContent() { + return (String)readProperty("content"); + } + + public void setTitle(String title) { + writeProperty("title", title); + } + public String getTitle() { + return (String)readProperty("title"); + } + + public void setAuthor(Author author) { + setToOneTarget("author", author, true); + } + + public Author getAuthor() { + return (Author)readProperty("author"); + } + + +} diff --git a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java new file mode 100644 index 0000000000..3d068423c8 --- /dev/null +++ b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java @@ -0,0 +1,52 @@ +package com.baeldung.apachecayenne.persistent.auto; + +import java.util.List; + +import org.apache.cayenne.CayenneDataObject; +import org.apache.cayenne.exp.Property; + +import com.baeldung.apachecayenne.persistent.Article; + +/** + * Class _Author was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public abstract class _Author extends CayenneDataObject { + + private static final long serialVersionUID = 1L; + + public static final String ID_PK_COLUMN = "id"; + + public static final Property FIRSTNAME = Property.create("firstname", String.class); + public static final Property LASTNAME = Property.create("lastname", String.class); + public static final Property> ARTICLES = Property.create("articles", List.class); + + public void setFirstname(String firstname) { + writeProperty("firstname", firstname); + } + public String getFirstname() { + return (String)readProperty("firstname"); + } + + public void setLastname(String lastname) { + writeProperty("lastname", lastname); + } + public String getLastname() { + return (String)readProperty("lastname"); + } + + public void addToArticles(Article obj) { + addToManyTarget("articles", obj, true); + } + public void removeFromArticles(Article obj) { + removeToManyTarget("articles", obj, true); + } + @SuppressWarnings("unchecked") + public List
getArticles() { + return (List
)readProperty("articles"); + } + + +} diff --git a/apache-cayenne/src/main/resources/cayenne-project.xml b/apache-cayenne/src/main/resources/cayenne-project.xml new file mode 100644 index 0000000000..3f3c59e0e9 --- /dev/null +++ b/apache-cayenne/src/main/resources/cayenne-project.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/apache-cayenne/src/main/resources/datamap.map.xml b/apache-cayenne/src/main/resources/datamap.map.xml new file mode 100644 index 0000000000..dc78ad4348 --- /dev/null +++ b/apache-cayenne/src/main/resources/datamap.map.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java new file mode 100644 index 0000000000..da9667b029 --- /dev/null +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java @@ -0,0 +1,140 @@ +package com.baeldung.apachecayenne; + +import com.baeldung.apachecayenne.persistent.Article; +import com.baeldung.apachecayenne.persistent.Author; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.configuration.server.ServerRuntime; +import org.apache.cayenne.query.ObjectSelect; +import org.apache.cayenne.query.SQLTemplate; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertNull; + + +public class CayenneOperationTests { + private static ObjectContext context = null; + + @BeforeClass + public static void setupTheCayenneContext(){ + ServerRuntime cayenneRuntime = ServerRuntime.builder() + .addConfig("cayenne-project.xml") + .build(); + context = cayenneRuntime.newContext(); + } + + @After + public void deleteAllRecords(){ + SQLTemplate deleteArticles = new SQLTemplate(Article.class, "delete from article"); + SQLTemplate deleteAuthors = new SQLTemplate(Author.class, "delete from author"); + + context.performGenericQuery(deleteArticles); + context.performGenericQuery(deleteAuthors); + } + + @Test + public void givenAuthor_whenInsert_thenWeGetOneRecordInTheDatabase(){ + Author author = context.newObject(Author.class); + author.setFirstname("Paul"); + author.setLastname("Smith"); + + context.commitChanges(); + + long records = ObjectSelect.dataRowQuery(Author.class).selectCount(context); + assertEquals(1, records); + } + + @Test + public void givenAuthor_whenInsert_andQueryByFirstName_thenWeGetTheAuthor(){ + Author author = context.newObject(Author.class); + author.setFirstname("Paul"); + author.setLastname("Smith"); + + context.commitChanges(); + + Author expectedAuthor = ObjectSelect.query(Author.class) + .where(Author.FIRSTNAME.eq("Paul")) + .selectOne(context); + + assertEquals("Paul", expectedAuthor.getFirstname()); + assertEquals("Smith", expectedAuthor.getLastname()); + } + + @Test + public void givenTwoAuthor_whenInsert_andQueryAll_thenWeGetTwoAuthors(){ + Author firstAuthor = context.newObject(Author.class); + firstAuthor.setFirstname("Paul"); + firstAuthor.setLastname("Smith"); + + Author secondAuthor = context.newObject(Author.class); + secondAuthor.setFirstname("Ludovic"); + secondAuthor.setLastname("Garcia"); + + context.commitChanges(); + + List authors = ObjectSelect.query(Author.class).select(context); + assertEquals(2, authors.size()); + } + + @Test + public void givenAuthor_whenUpdating_thenWeGetAnUpatedeAuthor(){ + Author author = context.newObject(Author.class); + author.setFirstname("Paul"); + author.setLastname("Smith"); + context.commitChanges(); + + Author expectedAuthor = ObjectSelect.query(Author.class) + .where(Author.FIRSTNAME.eq("Paul")) + .selectOne(context); + expectedAuthor.setLastname("Smith 2"); + context.commitChanges(); + + assertEquals(author.getFirstname(), expectedAuthor.getFirstname()); + assertEquals(author.getLastname(), expectedAuthor.getLastname()); + } + + @Test + public void givenAuthor_whenDeleting_thenWeLostHisDetails(){ + Author author = context.newObject(Author.class); + author.setFirstname("Paul"); + author.setLastname("Smith"); + context.commitChanges(); + + Author savedAuthor = ObjectSelect.query(Author.class) + .where(Author.FIRSTNAME.eq("Paul")).selectOne(context); + if(savedAuthor != null) { + context.deleteObjects(author); + context.commitChanges(); + } + + Author expectedAuthor = ObjectSelect.query(Author.class) + .where(Author.FIRSTNAME.eq("Paul")).selectOne(context); + assertNull(expectedAuthor); + } + + @Test + public void givenAuthor_whenAttachingToArticle_thenTheRelationIsMade(){ + Author author = context.newObject(Author.class); + author.setFirstname("Paul"); + author.setLastname("Smith"); + + Article article = context.newObject(Article.class); + article.setTitle("My post title"); + article.setContent("The content"); + article.setAuthor(author); + + context.commitChanges(); + + Author expectedAuthor = ObjectSelect.query(Author.class) + .where(Author.LASTNAME.eq("Smith")) + .selectOne(context); + + Article expectedArticle = (expectedAuthor.getArticles()).get(0); + assertEquals(article.getTitle(), expectedArticle.getTitle()); + } + +} diff --git a/pom.xml b/pom.xml index dfa7e09acc..083cee017b 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,7 @@ + apache-cayenne aws akka-streams algorithms From 8b9037ff0a30d0f045a24d9173eca4b28c4085bf Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sat, 23 Sep 2017 00:24:55 +0100 Subject: [PATCH 10/36] BAEL-1107: update formating and version of libs --- apache-cayenne/pom.xml | 2 +- .../apachecayenne/CayenneOperationTests.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apache-cayenne/pom.xml b/apache-cayenne/pom.xml index 23837d7019..52631e8594 100644 --- a/apache-cayenne/pom.xml +++ b/apache-cayenne/pom.xml @@ -20,7 +20,7 @@ UTF-8 UTF-8 1.8 - 5.1.31 + 5.1.44 4.0.M5 4.12 diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java index da9667b029..b92096c0fa 100644 --- a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java @@ -20,7 +20,7 @@ public class CayenneOperationTests { private static ObjectContext context = null; @BeforeClass - public static void setupTheCayenneContext(){ + public static void setupTheCayenneContext() { ServerRuntime cayenneRuntime = ServerRuntime.builder() .addConfig("cayenne-project.xml") .build(); @@ -28,7 +28,7 @@ public class CayenneOperationTests { } @After - public void deleteAllRecords(){ + public void deleteAllRecords() { SQLTemplate deleteArticles = new SQLTemplate(Article.class, "delete from article"); SQLTemplate deleteAuthors = new SQLTemplate(Author.class, "delete from author"); @@ -37,7 +37,7 @@ public class CayenneOperationTests { } @Test - public void givenAuthor_whenInsert_thenWeGetOneRecordInTheDatabase(){ + public void givenAuthor_whenInsert_thenWeGetOneRecordInTheDatabase() { Author author = context.newObject(Author.class); author.setFirstname("Paul"); author.setLastname("Smith"); @@ -49,7 +49,7 @@ public class CayenneOperationTests { } @Test - public void givenAuthor_whenInsert_andQueryByFirstName_thenWeGetTheAuthor(){ + public void givenAuthor_whenInsert_andQueryByFirstName_thenWeGetTheAuthor() { Author author = context.newObject(Author.class); author.setFirstname("Paul"); author.setLastname("Smith"); @@ -65,7 +65,7 @@ public class CayenneOperationTests { } @Test - public void givenTwoAuthor_whenInsert_andQueryAll_thenWeGetTwoAuthors(){ + public void givenTwoAuthor_whenInsert_andQueryAll_thenWeGetTwoAuthors() { Author firstAuthor = context.newObject(Author.class); firstAuthor.setFirstname("Paul"); firstAuthor.setLastname("Smith"); @@ -81,7 +81,7 @@ public class CayenneOperationTests { } @Test - public void givenAuthor_whenUpdating_thenWeGetAnUpatedeAuthor(){ + public void givenAuthor_whenUpdating_thenWeGetAnUpatedeAuthor() { Author author = context.newObject(Author.class); author.setFirstname("Paul"); author.setLastname("Smith"); @@ -98,7 +98,7 @@ public class CayenneOperationTests { } @Test - public void givenAuthor_whenDeleting_thenWeLostHisDetails(){ + public void givenAuthor_whenDeleting_thenWeLostHisDetails() { Author author = context.newObject(Author.class); author.setFirstname("Paul"); author.setLastname("Smith"); @@ -117,7 +117,7 @@ public class CayenneOperationTests { } @Test - public void givenAuthor_whenAttachingToArticle_thenTheRelationIsMade(){ + public void givenAuthor_whenAttachingToArticle_thenTheRelationIsMade() { Author author = context.newObject(Author.class); author.setFirstname("Paul"); author.setLastname("Smith"); From 44d5a03c0dfcc9a50b8e6f89aaeac7364eb4a2c9 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sun, 24 Sep 2017 14:15:12 +0100 Subject: [PATCH 11/36] BAEL-1107: update properties of Author --- .../persistent/auto/_Author.java | 18 +++------ .../src/main/resources/datamap.map.xml | 6 +-- .../apachecayenne/CayenneOperationTests.java | 39 +++++++------------ 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java index 3d068423c8..4d3bb090ca 100644 --- a/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java +++ b/apache-cayenne/src/main/java/com/baeldung/apachecayenne/persistent/auto/_Author.java @@ -19,22 +19,14 @@ public abstract class _Author extends CayenneDataObject { public static final String ID_PK_COLUMN = "id"; - public static final Property FIRSTNAME = Property.create("firstname", String.class); - public static final Property LASTNAME = Property.create("lastname", String.class); + public static final Property NAME = Property.create("name", String.class); public static final Property> ARTICLES = Property.create("articles", List.class); - public void setFirstname(String firstname) { - writeProperty("firstname", firstname); + public void setName(String name) { + writeProperty("name", name); } - public String getFirstname() { - return (String)readProperty("firstname"); - } - - public void setLastname(String lastname) { - writeProperty("lastname", lastname); - } - public String getLastname() { - return (String)readProperty("lastname"); + public String getName() { + return (String)readProperty("name"); } public void addToArticles(Article obj) { diff --git a/apache-cayenne/src/main/resources/datamap.map.xml b/apache-cayenne/src/main/resources/datamap.map.xml index dc78ad4348..3305649669 100644 --- a/apache-cayenne/src/main/resources/datamap.map.xml +++ b/apache-cayenne/src/main/resources/datamap.map.xml @@ -11,17 +11,15 @@ - - + - - + diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java index b92096c0fa..8a0d210d8d 100644 --- a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneOperationTests.java @@ -39,8 +39,7 @@ public class CayenneOperationTests { @Test public void givenAuthor_whenInsert_thenWeGetOneRecordInTheDatabase() { Author author = context.newObject(Author.class); - author.setFirstname("Paul"); - author.setLastname("Smith"); + author.setName("Paul"); context.commitChanges(); @@ -51,28 +50,24 @@ public class CayenneOperationTests { @Test public void givenAuthor_whenInsert_andQueryByFirstName_thenWeGetTheAuthor() { Author author = context.newObject(Author.class); - author.setFirstname("Paul"); - author.setLastname("Smith"); + author.setName("Paul"); context.commitChanges(); Author expectedAuthor = ObjectSelect.query(Author.class) - .where(Author.FIRSTNAME.eq("Paul")) + .where(Author.NAME.eq("Paul")) .selectOne(context); - assertEquals("Paul", expectedAuthor.getFirstname()); - assertEquals("Smith", expectedAuthor.getLastname()); + assertEquals("Paul", expectedAuthor.getName()); } @Test public void givenTwoAuthor_whenInsert_andQueryAll_thenWeGetTwoAuthors() { Author firstAuthor = context.newObject(Author.class); - firstAuthor.setFirstname("Paul"); - firstAuthor.setLastname("Smith"); + firstAuthor.setName("Paul"); Author secondAuthor = context.newObject(Author.class); - secondAuthor.setFirstname("Ludovic"); - secondAuthor.setLastname("Garcia"); + secondAuthor.setName("Ludovic"); context.commitChanges(); @@ -83,44 +78,40 @@ public class CayenneOperationTests { @Test public void givenAuthor_whenUpdating_thenWeGetAnUpatedeAuthor() { Author author = context.newObject(Author.class); - author.setFirstname("Paul"); - author.setLastname("Smith"); + author.setName("Paul"); context.commitChanges(); Author expectedAuthor = ObjectSelect.query(Author.class) - .where(Author.FIRSTNAME.eq("Paul")) + .where(Author.NAME.eq("Paul")) .selectOne(context); - expectedAuthor.setLastname("Smith 2"); + expectedAuthor.setName("Garcia"); context.commitChanges(); - assertEquals(author.getFirstname(), expectedAuthor.getFirstname()); - assertEquals(author.getLastname(), expectedAuthor.getLastname()); + assertEquals(author.getName(), expectedAuthor.getName()); } @Test public void givenAuthor_whenDeleting_thenWeLostHisDetails() { Author author = context.newObject(Author.class); - author.setFirstname("Paul"); - author.setLastname("Smith"); + author.setName("Paul"); context.commitChanges(); Author savedAuthor = ObjectSelect.query(Author.class) - .where(Author.FIRSTNAME.eq("Paul")).selectOne(context); + .where(Author.NAME.eq("Paul")).selectOne(context); if(savedAuthor != null) { context.deleteObjects(author); context.commitChanges(); } Author expectedAuthor = ObjectSelect.query(Author.class) - .where(Author.FIRSTNAME.eq("Paul")).selectOne(context); + .where(Author.NAME.eq("Paul")).selectOne(context); assertNull(expectedAuthor); } @Test public void givenAuthor_whenAttachingToArticle_thenTheRelationIsMade() { Author author = context.newObject(Author.class); - author.setFirstname("Paul"); - author.setLastname("Smith"); + author.setName("Paul"); Article article = context.newObject(Article.class); article.setTitle("My post title"); @@ -130,7 +121,7 @@ public class CayenneOperationTests { context.commitChanges(); Author expectedAuthor = ObjectSelect.query(Author.class) - .where(Author.LASTNAME.eq("Smith")) + .where(Author.NAME.eq("Paul")) .selectOne(context); Article expectedArticle = (expectedAuthor.getArticles()).get(0); From 5672ec1f2dfa511c2a2b58ac12e65cbc971b7d9e Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 5 Oct 2017 03:14:25 +0100 Subject: [PATCH 12/36] BAEL-1157: Apache Cayenne - Advanced Querying --- .../CayenneAdvancedOperationTests.java | 255 ++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java new file mode 100644 index 0000000000..613ef757b4 --- /dev/null +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java @@ -0,0 +1,255 @@ +package com.baeldung.apachecayenne; + +import com.baeldung.apachecayenne.persistent.Article; +import com.baeldung.apachecayenne.persistent.Author; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.configuration.server.ServerRuntime; +import org.apache.cayenne.query.ObjectSelect; +import org.apache.cayenne.query.SQLTemplate; +import org.apache.cayenne.query.SelectQuery; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class CayenneAdvancedOperationTests { + private static ObjectContext context = null; + + @BeforeClass + public static void setupTheCayenneContext() { + ServerRuntime cayenneRuntime = ServerRuntime.builder() + .addConfig("cayenne-project.xml") + .build(); + context = cayenneRuntime.newContext(); + } + + @Before + public void saveThreeAuthors() { + Author authorOne = context.newObject(Author.class); + authorOne.setName("Paul Xavier"); + Author authorTwo = context.newObject(Author.class); + authorTwo.setName("pAuL Smith"); + Author authorThree = context.newObject(Author.class); + authorThree.setName("Vicky Sarra"); + context.commitChanges(); + } + + @After + public void deleteAllAuthors() { + SQLTemplate deleteAuthors = new SQLTemplate(Author.class, "delete from author"); + context.performGenericQuery(deleteAuthors); + } + + @Test + public void givenAuthors_whenFindAllSQLTmplt_thenWeGetThreeAuthors() { + SQLTemplate select = new SQLTemplate(Author.class, "select * from Author"); + List authors = context.performQuery(select); + + assertEquals(authors.size(), 3); + } + + @Test + public void givenAuthors_whenFindByNameSQLTmplt_thenWeGetOneAuthor() { + SQLTemplate select = new SQLTemplate(Author.class, "select * from Author where name = 'Vicky Sarra'"); + List authors = context.performQuery(select); + Author author = authors.get(0); + + assertEquals(authors.size(), 1); + assertEquals(author.getName(), "Vicky Sarra"); + } + + @Test + public void givenAuthors_whenLikeSltQry_thenWeGetOneAuthor() { + Expression qualifier = ExpressionFactory.likeExp(Author.NAME.getName(), "Paul%"); + SelectQuery query = new SelectQuery(Author.class, qualifier); + List authorsTwo = context.performQuery(query); + + assertEquals(authorsTwo.size(), 1); + } + + @Test + public void givenAuthors_whenCtnsIgnorCaseSltQry_thenWeGetTwoAuthors() { + Expression qualifier = ExpressionFactory.containsIgnoreCaseExp(Author.NAME.getName(), "Paul"); + SelectQuery query = new SelectQuery(Author.class, qualifier); + List authors = context.performQuery(query); + + assertEquals(authors.size(), 2); + } + + @Test + public void givenAuthors_whenCtnsIgnorCaseEndsWSltQry_thenWeGetTwoAuthors() { + Expression qualifier = ExpressionFactory.containsIgnoreCaseExp(Author.NAME.getName(), "Paul") + .andExp(ExpressionFactory.endsWithExp(Author.NAME.getName(), "h")); + SelectQuery query = new SelectQuery(Author.class, qualifier); + List authors = context.performQuery(query); + + Author author = authors.get(0); + + assertEquals(authors.size(), 1); + assertEquals(author.getName(), "pAuL Smith"); + } + + @Test + public void givenAuthors_whenAscOrderingSltQry_thenWeGetOrderedAuthors() { + SelectQuery query = new SelectQuery(Author.class); + query.addOrdering(Author.NAME.asc()); + + List authors = query.select(context); + Author firstAuthor = authors.get(0); + + assertEquals(authors.size(), 3); + assertEquals(firstAuthor.getName(), "Paul Xavier"); + } + + @Test + public void givenAuthors_whenDescOrderingSltQry_thenWeGetOrderedAuthors() { + SelectQuery query = new SelectQuery(Author.class); + query.addOrdering(Author.NAME.desc()); + + List authors = query.select(context); + Author firstAuthor = authors.get(0); + + assertEquals(authors.size(), 3); + assertEquals(firstAuthor.getName(), "pAuL Smith"); + } + + @Test + public void givenAuthors_onContainsObjS_thenWeGetOneRecord() { + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.contains("Paul")) + .select(context); + + assertEquals(authors.size(), 1); + } + + @Test + public void givenAuthors_whenLikeObjS_thenWeGetTwoAuthors() { + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.likeIgnoreCase("Paul%")) + .select(context); + + assertEquals(authors.size(), 2); + } + + @Test + public void givenTwoAuthor_whenEndsWithObjS_thenWeGetOrderedAuthors() { + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.endsWith("Sarra")) + .select(context); + Author firstAuthor = authors.get(0); + + assertEquals(authors.size(), 1); + assertEquals(firstAuthor.getName(), "Vicky Sarra"); + } + + @Test + public void givenTwoAuthor_whenInObjS_thenWeGetAuthors() { + String [] args = {"Paul Xavier", "pAuL Smith", "Vicky Sarra"}; + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.in(Arrays.asList(args))) + .select(context); + + assertEquals(authors.size(), 3); + } + + @Test + public void givenTwoAuthor_whenNinObjS_thenWeGetAuthors() { + String [] args = {"Paul Xavier", "pAuL Smith"}; + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.nin(Arrays.asList(args))) + .select(context); + Author author = authors.get(0); + + assertEquals(authors.size(), 1); + assertEquals(author.getName(), "Vicky Sarra"); + } + + @Test + public void givenTwoAuthor_whenIsNotNullObjS_thenWeGetAuthors() { + List authors = ObjectSelect.query(Author.class) + .where(Author.NAME.isNotNull()) + .select(context); + + assertEquals(authors.size(), 3); + } + + @Test + public void givenAuthors_whenFindAllEJBQL_thenWeGetThreeAuthors() { + EJBQLQuery query = new EJBQLQuery("select a FROM Author a"); + List authors = context.performQuery(query); + + assertEquals(authors.size(), 3); + } + + @Test + public void givenAuthors_whenFindByNameEJBQL_thenWeGetOneAuthor() { + EJBQLQuery query = new EJBQLQuery("select a FROM Author a WHERE a.name = 'Vicky Sarra'"); + List authors = context.performQuery(query); + Author author = authors.get(0); + + assertEquals(authors.size(), 1); + assertEquals(author.getName(), "Vicky Sarra"); + } + + @Test + public void givenAuthors_whenUpdadingByNameEJBQL_thenWeGetTheUpdatedAuthor() { + EJBQLQuery query = new EJBQLQuery("UPDATE Author AS a SET a.name = 'Vicky Edison' WHERE a.name = 'Vicky Sarra'"); + QueryResponse queryResponse = context.performGenericQuery(query); + + EJBQLQuery queryUpdatedAuthor = new EJBQLQuery("select a FROM Author a WHERE a.name = 'Vicky Edison'"); + List authors = context.performQuery(queryUpdatedAuthor); + Author author = authors.get(0); + + assertNotNull(author); + } + + @Test + public void givenAuthors_whenSeletingNamesEJBQL_thenWeGetListWithSizeThree() { + String [] args = {"Paul Xavier", "pAuL Smith", "Vicky Sarra"}; + List names = Arrays.asList(args); + EJBQLQuery query = new EJBQLQuery("select a.name FROM Author a"); + List nameList = context.performQuery(query); + + Collections.sort(names); + Collections.sort(nameList); + + assertEquals(names.size(), 3); + assertEquals(nameList.size(), 3); + assertEquals(names, nameList); + } + + @Test + public void givenAuthors_whenDeletingAllWithEJB_thenWeGetNoAuthor() { + EJBQLQuery deleteQuery = new EJBQLQuery("delete FROM Author"); + EJBQLQuery findAllQuery = new EJBQLQuery("select a FROM Author a"); + + context.performQuery(deleteQuery); + List objects = context.performQuery(findAllQuery); + + assertEquals(objects.size(), 0); + } + + @Test + public void givenAuthors_whenInsertingSQLExec_thenWeGetNewAuthor() { + int inserted = SQLExec + .query("INSERT INTO Author (name) VALUES ('Baeldung')") + .update(context); + + assertEquals(inserted, 1); + } + + @Test + public void givenAuthors_whenUpdatingSQLExec_thenItsUpdated() { + int updated = SQLExec + .query("UPDATE Author SET name = 'Baeldung' WHERE name = 'Vicky Sarra'") + .update(context); + + assertEquals(updated, 1); + } +} From 0dbfa53ae074e42cf354cd3939e97edab50872f5 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 5 Oct 2017 03:47:28 +0100 Subject: [PATCH 13/36] BAEL-1157: Fix imports --- .../CayenneAdvancedOperationTests.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java index 613ef757b4..ea10b59dd2 100644 --- a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java @@ -1,22 +1,23 @@ package com.baeldung.apachecayenne; -import com.baeldung.apachecayenne.persistent.Article; import com.baeldung.apachecayenne.persistent.Author; import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.QueryResponse; import org.apache.cayenne.configuration.server.ServerRuntime; -import org.apache.cayenne.query.ObjectSelect; -import org.apache.cayenne.query.SQLTemplate; -import org.apache.cayenne.query.SelectQuery; +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; +import org.apache.cayenne.query.*; import org.junit.After; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import static junit.framework.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; public class CayenneAdvancedOperationTests { private static ObjectContext context = null; From 3f825c5b96cbd7105820616774c988c1359eb344 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 5 Oct 2017 04:17:56 +0100 Subject: [PATCH 14/36] BAEL-1157: code indentation --- .../CayenneAdvancedOperationTests.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java index ea10b59dd2..ddfe9325d3 100644 --- a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java @@ -25,8 +25,8 @@ public class CayenneAdvancedOperationTests { @BeforeClass public static void setupTheCayenneContext() { ServerRuntime cayenneRuntime = ServerRuntime.builder() - .addConfig("cayenne-project.xml") - .build(); + .addConfig("cayenne-project.xml") + .build(); context = cayenneRuntime.newContext(); } @@ -123,8 +123,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenAuthors_onContainsObjS_thenWeGetOneRecord() { List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.contains("Paul")) - .select(context); + .where(Author.NAME.contains("Paul")) + .select(context); assertEquals(authors.size(), 1); } @@ -132,8 +132,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenAuthors_whenLikeObjS_thenWeGetTwoAuthors() { List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.likeIgnoreCase("Paul%")) - .select(context); + .where(Author.NAME.likeIgnoreCase("Paul%")) + .select(context); assertEquals(authors.size(), 2); } @@ -141,8 +141,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenTwoAuthor_whenEndsWithObjS_thenWeGetOrderedAuthors() { List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.endsWith("Sarra")) - .select(context); + .where(Author.NAME.endsWith("Sarra")) + .select(context); Author firstAuthor = authors.get(0); assertEquals(authors.size(), 1); @@ -153,8 +153,8 @@ public class CayenneAdvancedOperationTests { public void givenTwoAuthor_whenInObjS_thenWeGetAuthors() { String [] args = {"Paul Xavier", "pAuL Smith", "Vicky Sarra"}; List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.in(Arrays.asList(args))) - .select(context); + .where(Author.NAME.in(Arrays.asList(args))) + .select(context); assertEquals(authors.size(), 3); } @@ -163,8 +163,8 @@ public class CayenneAdvancedOperationTests { public void givenTwoAuthor_whenNinObjS_thenWeGetAuthors() { String [] args = {"Paul Xavier", "pAuL Smith"}; List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.nin(Arrays.asList(args))) - .select(context); + .where(Author.NAME.nin(Arrays.asList(args))) + .select(context); Author author = authors.get(0); assertEquals(authors.size(), 1); @@ -174,8 +174,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenTwoAuthor_whenIsNotNullObjS_thenWeGetAuthors() { List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.isNotNull()) - .select(context); + .where(Author.NAME.isNotNull()) + .select(context); assertEquals(authors.size(), 3); } @@ -239,8 +239,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenAuthors_whenInsertingSQLExec_thenWeGetNewAuthor() { int inserted = SQLExec - .query("INSERT INTO Author (name) VALUES ('Baeldung')") - .update(context); + .query("INSERT INTO Author (name) VALUES ('Baeldung')") + .update(context); assertEquals(inserted, 1); } @@ -248,8 +248,8 @@ public class CayenneAdvancedOperationTests { @Test public void givenAuthors_whenUpdatingSQLExec_thenItsUpdated() { int updated = SQLExec - .query("UPDATE Author SET name = 'Baeldung' WHERE name = 'Vicky Sarra'") - .update(context); + .query("UPDATE Author SET name = 'Baeldung' WHERE name = 'Vicky Sarra'") + .update(context); assertEquals(updated, 1); } From efc58b5b79d25b0a3624da95a9ef6c200bd6d830 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Mon, 9 Oct 2017 17:31:54 +0100 Subject: [PATCH 15/36] BAEL-1157: Update list of author names --- .../apachecayenne/CayenneAdvancedOperationTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java index ddfe9325d3..cd563b6270 100644 --- a/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java +++ b/apache-cayenne/src/test/java/com/baeldung/apachecayenne/CayenneAdvancedOperationTests.java @@ -151,20 +151,20 @@ public class CayenneAdvancedOperationTests { @Test public void givenTwoAuthor_whenInObjS_thenWeGetAuthors() { - String [] args = {"Paul Xavier", "pAuL Smith", "Vicky Sarra"}; + List names = Arrays.asList("Paul Xavier", "pAuL Smith", "Vicky Sarra"); List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.in(Arrays.asList(args))) - .select(context); + .where(Author.NAME.in(names)) + .select(context); assertEquals(authors.size(), 3); } @Test public void givenTwoAuthor_whenNinObjS_thenWeGetAuthors() { - String [] args = {"Paul Xavier", "pAuL Smith"}; + List names = Arrays.asList("Paul Xavier", "pAuL Smith"); List authors = ObjectSelect.query(Author.class) - .where(Author.NAME.nin(Arrays.asList(args))) - .select(context); + .where(Author.NAME.nin(names)) + .select(context); Author author = authors.get(0); assertEquals(authors.size(), 1); From c3a2179b9bcfb07fb3603cfc76be735e8924e41c Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sun, 22 Oct 2017 03:45:08 +0100 Subject: [PATCH 16/36] BAEL-132: Configure Jenkins to Run and Show Jmeter Tests --- pom.xml | 1 + spring-jmeter-jenkins | 1 + 2 files changed, 2 insertions(+) create mode 160000 spring-jmeter-jenkins diff --git a/pom.xml b/pom.xml index c3915e4fce..996ca91f2e 100644 --- a/pom.xml +++ b/pom.xml @@ -168,6 +168,7 @@ spring-hibernate5 spring-integration spring-jersey + spring-jmeter-jenkins spring-jms spring-jooq spring-jpa diff --git a/spring-jmeter-jenkins b/spring-jmeter-jenkins new file mode 160000 index 0000000000..a1b44b4c48 --- /dev/null +++ b/spring-jmeter-jenkins @@ -0,0 +1 @@ +Subproject commit a1b44b4c487164577be3c7eb4bf215d39a0700df From 0623fb5b172c5637b93627d02b4ad218d83d8075 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sun, 22 Oct 2017 16:14:18 +0100 Subject: [PATCH 17/36] Removed submodule spring-jmeter-jenkins --- spring-jmeter-jenkins | 1 - 1 file changed, 1 deletion(-) delete mode 160000 spring-jmeter-jenkins diff --git a/spring-jmeter-jenkins b/spring-jmeter-jenkins deleted file mode 160000 index a1b44b4c48..0000000000 --- a/spring-jmeter-jenkins +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a1b44b4c487164577be3c7eb4bf215d39a0700df From 3d0fe787cfaee47105b1b1305bc376afec6aeabd Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Sun, 22 Oct 2017 16:15:50 +0100 Subject: [PATCH 18/36] Commit again spring-jmeter-jenkins --- spring-jmeter-jenkins/.gitignore | 24 ++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 49502 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + spring-jmeter-jenkins/README.md | 55 +++++ spring-jmeter-jenkins/mvnw | 233 ++++++++++++++++++ spring-jmeter-jenkins/mvnw.cmd | 145 +++++++++++ spring-jmeter-jenkins/pom.xml | 52 ++++ .../SpringJMeterJenkinsApplication.java | 13 + .../java/com/baeldung/domain/Student.java | 66 +++++ .../repository/StudentRepository.java | 7 + .../src/main/resources/JMeter-Jenkins.jmx | 96 ++++++++ .../src/main/resources/application.properties | 14 ++ .../SpringJMeterJenkinsApplicationTests.java | 16 ++ 13 files changed, 722 insertions(+) create mode 100644 spring-jmeter-jenkins/.gitignore create mode 100644 spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties create mode 100644 spring-jmeter-jenkins/README.md create mode 100755 spring-jmeter-jenkins/mvnw create mode 100644 spring-jmeter-jenkins/mvnw.cmd create mode 100644 spring-jmeter-jenkins/pom.xml create mode 100644 spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java create mode 100644 spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java create mode 100644 spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java create mode 100644 spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx create mode 100644 spring-jmeter-jenkins/src/main/resources/application.properties create mode 100644 spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationTests.java diff --git a/spring-jmeter-jenkins/.gitignore b/spring-jmeter-jenkins/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-jmeter-jenkins/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.jar b/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5fd4d5023f1463b5ba3970e33c460c1eb26d748d GIT binary patch literal 49502 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%0A$pwhjXzyA0ZzErH{1@M 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 OJOEd-=rxTO#Qy`$*1Hh^ literal 0 HcmV?d00001 diff --git a/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties b/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..c954cec91c --- /dev/null +++ b/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip diff --git a/spring-jmeter-jenkins/README.md b/spring-jmeter-jenkins/README.md new file mode 100644 index 0000000000..49c18122a2 --- /dev/null +++ b/spring-jmeter-jenkins/README.md @@ -0,0 +1,55 @@ +BASIC CRUD API with Spring Boot +================================ + +This is the code of a simple API for some CRUD operations realised for a seminar at [FGI](www.fgi-ud.org) using Spring Boot. + +### Demo +* API: The online version **is**/**will be** hosted here: https://fgi-tcheck.herokuapp.com +* Mobile version is also opensource and located here: https://github.com/valdesekamdem/tcheck-mobile + +### Features +#### Currently Implemented +* CRUD + * Student + +#### To DO +* Validations of input with: [Spring Data Rest Validators](http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html) + + +### Requirements + +- Maven +- JDK 8 +- MongoDB + +### Running + +To build and start the server simply type + +```bash +$ mvn clean install +$ mvn spring-boot:run -Dserver.port=8989 +``` + +### Available CRUD + +You can see what crud operation are available using curl: + +```bash +$ curl localhost:8080 +``` +You can view existing student objects with this command: + +```bash +$ curl localhost:8080/students +``` +Or create a new one via a POST: + +```bash +$ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "lastName" : "Orleando", "phoneNumber": "+237 545454545", "email": "mymail@yahoo.fr" }' localhost:8080/students +``` + + +Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) + +Enjoy it :) \ No newline at end of file diff --git a/spring-jmeter-jenkins/mvnw b/spring-jmeter-jenkins/mvnw new file mode 100755 index 0000000000..a1ba1bf554 --- /dev/null +++ b/spring-jmeter-jenkins/mvnw @@ -0,0 +1,233 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + 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 + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} "$@" diff --git a/spring-jmeter-jenkins/mvnw.cmd b/spring-jmeter-jenkins/mvnw.cmd new file mode 100644 index 0000000000..2b934e89dd --- /dev/null +++ b/spring-jmeter-jenkins/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% \ No newline at end of file diff --git a/spring-jmeter-jenkins/pom.xml b/spring-jmeter-jenkins/pom.xml new file mode 100644 index 0000000000..38b5f98e45 --- /dev/null +++ b/spring-jmeter-jenkins/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + spring-jmeter-jenkins + 0.0.1-SNAPSHOT + jar + + spring-jmeter-jenkins + Run and Show JMeter test with Jenkins + + + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-5 + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java b/spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java new file mode 100644 index 0000000000..3bc1f64f41 --- /dev/null +++ b/spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@SpringBootApplication +@EnableMongoRepositories +public class SpringJMeterJenkinsApplication { + public static void main(String[] args) { + SpringApplication.run(SpringJMeterJenkinsApplication.class, args); + } +} diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java b/spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java new file mode 100644 index 0000000000..0f6150fc48 --- /dev/null +++ b/spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java @@ -0,0 +1,66 @@ +package com.baeldung.domain; + +import javax.validation.constraints.NotNull; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.io.Serializable; + +@Document(collection = "STUDENT") +public class Student implements Serializable { + + @Id + private String id; + @NotNull + private String firstName; + private String lastName; + @NotNull + private String phoneNumber; + private String email; + + public String getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public String toString() { + return "Student{" + + "firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", phoneNumber='" + phoneNumber + '\'' + + ", email='" + email + '\'' + + '}'; + } +} diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java b/spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java new file mode 100644 index 0000000000..d0ca7d8510 --- /dev/null +++ b/spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.repository; + +import org.springframework.data.mongodb.repository.MongoRepository; +import com.baeldung.domain.Student; + +public interface StudentRepository extends MongoRepository { +} diff --git a/spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx b/spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx new file mode 100644 index 0000000000..49ce2dec1d --- /dev/null +++ b/spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx @@ -0,0 +1,96 @@ + + + + + + false + false + + + + + + + + continue + + false + 1 + + 5 + 1 + 1507776008000 + 1507776008000 + false + + + + + + + + + localhost + 8989 + + + /students + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + + + + + + + 10 + + + + + + + true + + + + diff --git a/spring-jmeter-jenkins/src/main/resources/application.properties b/spring-jmeter-jenkins/src/main/resources/application.properties new file mode 100644 index 0000000000..c7d86e14b0 --- /dev/null +++ b/spring-jmeter-jenkins/src/main/resources/application.properties @@ -0,0 +1,14 @@ +# the db host +spring.data.mongodb.host=localhost +# the connection port (defaults to 27107) +spring.data.mongodb.port=27017 +# The database's name +spring.data.mongodb.database=JMeter-Jenkins + +# Or this +# spring.data.mongodb.uri=mongodb://localhost/JMeter-Jenkins + +# spring.data.mongodb.username= +# spring.data.mongodb.password= + +spring.data.mongodb.repositories.enabled=true \ No newline at end of file diff --git a/spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationTests.java b/spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationTests.java new file mode 100644 index 0000000000..b39a5605b1 --- /dev/null +++ b/spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationTests.java @@ -0,0 +1,16 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringJMeterJenkinsApplicationTests { + + @Test + public void contextLoads() { + } + +} From 29fe38bfdeea959588886487c3728573c2b0bb66 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 15 Nov 2017 05:09:41 +0100 Subject: [PATCH 19/36] BAEL-1190: JUnit 5 upgrade --- testing-modules/junit-5/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index 229703ccf5..2be8937d04 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -20,7 +20,7 @@ UTF-8 1.8 - 5.0.1 + 5.0.2 1.0.1 4.12.1 2.8.2 @@ -127,4 +127,4 @@ - \ No newline at end of file + From 4bf7fb23f665f4b29883ad0df53e0c86bb540fc0 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 29 Nov 2017 04:30:45 +0100 Subject: [PATCH 20/36] BAEL-720: Intro to Jenkins 2 and the power of pipelines --- pom.xml | 1 + spring-jenkins-pipeline/.gitignore | 24 ++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 49502 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + spring-jenkins-pipeline/README.md | 23 ++ spring-jenkins-pipeline/mvnw | 233 ++++++++++++++++++ spring-jenkins-pipeline/mvnw.cmd | 145 +++++++++++ spring-jenkins-pipeline/pom.xml | 97 ++++++++ .../SpringJenkinsPipelineApplication.java | 13 + .../java/com/baeldung/domain/Student.java | 73 ++++++ .../repository/StudentRepository.java | 7 + .../src/main/resources/application.properties | 14 ++ .../com/baeldung/SomeIntegrationTest.java | 37 +++ .../test/java/com/baeldung/SomeUnitTest.java | 11 + spring-jmeter-jenkins/README.md | 16 +- 15 files changed, 680 insertions(+), 15 deletions(-) create mode 100644 spring-jenkins-pipeline/.gitignore create mode 100644 spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.properties create mode 100644 spring-jenkins-pipeline/README.md create mode 100755 spring-jenkins-pipeline/mvnw create mode 100644 spring-jenkins-pipeline/mvnw.cmd create mode 100644 spring-jenkins-pipeline/pom.xml create mode 100644 spring-jenkins-pipeline/src/main/java/com/baeldung/SpringJenkinsPipelineApplication.java create mode 100644 spring-jenkins-pipeline/src/main/java/com/baeldung/domain/Student.java create mode 100644 spring-jenkins-pipeline/src/main/java/com/baeldung/repository/StudentRepository.java create mode 100644 spring-jenkins-pipeline/src/main/resources/application.properties create mode 100644 spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java create mode 100644 spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java diff --git a/pom.xml b/pom.xml index 20f7c4ffad..827c4ee4cf 100644 --- a/pom.xml +++ b/pom.xml @@ -173,6 +173,7 @@ spring-hibernate4 persistence-modules/spring-hibernate-5 spring-integration + spring-jenkins-pipeline spring-jersey spring-jmeter-jenkins spring-jms diff --git a/spring-jenkins-pipeline/.gitignore b/spring-jenkins-pipeline/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-jenkins-pipeline/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.jar b/spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5fd4d5023f1463b5ba3970e33c460c1eb26d748d GIT binary patch literal 49502 zcmb@tV|1n6wzeBvGe*U>ZQHh;%-Bg)Y}={WHY%yuwkkF%MnzxVwRUS~wY|@J_gP;% z^VfXZ{5793?z><89(^dufT2xlYVOQnYG>@?lA@vQF|UF0&X7tk8BUf?wq2J& zZe&>>paKUg4@;fwk0yeUPvM$yk)=f>TSFFB^a8f|_@mbE#MaBnd5qf6;hXq}c%IeK zn7gB0Kldbedq-vl@2wxJi{$%lufroKUjQLSFmt|<;M8~<5otM5ur#Dgc@ivmwRiYZW(Oco7kb8DWmo|a{coqYMU2raB9r6e9viK6MI3c&%jp05-Tf*O#6@8Ra=egYy01 z-V!G;_omANEvU-8!*>*)lWka9M<+IkNsrsenbXOfLc6qrYe`;lpst;vfs*70$z9UM zq%L>pFCOr$X*|9&3L2h;?VA9-IU*iR6FiGlJ=b~DzE5s^thxXUs4%~*zD#K&k>wZAU8 zpaa!M+Z-zjkfGK15N!&o<3=cgbZV7%ex@j^)Q9V`q^i;Fsbkbe6eHJ;dx{QbdCCs1 zdxq^WxoPsr`eiK3D0Ep}k$ank-0G&+lY!ZHDZBYEx%% z2FyE?Lb0cflLB)kDIj;G=m`^UO<4h(RWdF-DT>p{1J5J90!K!AgC0)?jxPbm$KUjg zJED+#7xQmAmr`(S%BQTV-c97As~r3zD$E;3S)@}p5udA@m6pLgRL5h-;m>LvCq?&Q zokC7Vnk-zBEaa;=Y;6(LJHS>mOJV&%0YfRdUOqbKZy~b z(905jIW0Pg;y`Yv2t+RnDvL4yGEUX*tK)JT6TWn4ik~L)fX#tAV!d8)+A)qWtSjcr z7s|f%f;*%XW!jiRvv9ayj@f&dc|1tKDc{O3BWcLGsn-OYyXRLXEOEwP4k?c`nIut0 z?4S;eO@EoynmkxHq>QpDL1q^wOQxrl))2qya?dk05^5hK? z{P6;WKHUaHw9B0dd&|xw&CYN2fVrn};Gq<=Z^QZk3e~HzzY~JrnPCs0XwMp#B<9Gm zw0?7h#4EY%O-ub6mi&O2vcpIkuM?st;RtEpKSz^Xr#3WHhpsZd!gh|_jGQ`KA30T- zKlz9vgB;pY^}Uh??nQKSzk>2&J+Qi*r3DeX4^$%2ag9^x_YckA-f9p_;8ulh(8j9~ zes{O#{v!m%n^el(VryTF-C%xfJJ$rZj)|Y|8o&))q9CEwg2;Wz&xzyHD=@T_B%b}C z=8G^*4*J4#jUJn{7-3^U(_uUp6E8+GDt#le)nya-Q4kL5ZGiFxT4bF+mX`whcif*? z>CL&Ryn3HHT^^QmWYr<}Q1_Jj7fOh}cS8r+^R#at-CnNl3!1_$96&7nR}gh}))7a0J&z-_eI))+{RCt)r8|7|sV9o01^9nv?aePxMqwPP!x|sNmnn&6{K$K*mVX9lxSAmcqAV1(hKA-=coeTb*otxTOGYXsh zW$31^q7L@<#y~SUYoNKP1JK?4|FQNQb$i8mCG@WhX9i_^;@M2f#!nq7_K*M!4lGz1 z5tfADkO7BZDLgVQ?k7C)f;$eqjHI&zgxhf}x$8^ZEwFfm-qY=+M+fbS)9r8fFE5H9 zv{WPU35cR8%z;(W%5<>y+E&v84J4^Y##N!$B++RI`CZ1i3IW9Nau=*pSxW&^Ov-F> zex=&9XYLVcm1Y?am>2VC`%gMev9$#~; zYwxYvMfeKFsd!OBB@eOb2QNHFcsfKm;&z{OVEUiYmQ}~L@>$Ms@|Ptf3jQO-=Q;1+ zFCw+p+Z3lK_FmIAYnk2V;o915cDM}%Ht5RH%w}P>Yg9{h1mZ}~R6tUII4X7i4-2i% z2Uiw3_uHR!d~5(s;p6btI@-xhAkRg9K|n#}PNT9Dw9P>z$3>30lP1(=mcQ|tpyv3@ ze1qU!69OAx4s7$8r7Y-#5I`m!BXq`f!6C(BtUlG-oq+liqMCS_D@0nSFc%y+N6_Zh zi%L3LhF3zZP{d1)L&SXxPD(fp@T@J;jZeNaf$zl>vAh7=tI z2;wS^QyRdZm~)Ur&!af;8eB8*7(F96K^=WbC$)#TWvB~Awo5AtPf8Il4snD}Xsqd< z>cH+gcg72nTg5tl>oFbwdT{BDyy1=f=4~h~L$)UX;FXa;NdSlyF{(YLrx&VDp`pQI zh3pQtC=d8i1V6yUmFon*LQsNYWen?eO-gSZ4cvYcdEd0klSxcBYw+|5AyCv6TT96h z{7Yh9`h}biU?3oBFn=d8>Hn`1Q*w6rgeX^QbC-WFwjY}Int0;qUny4WMjIee@#0%l z>YAWLVCNo1lp$>9L$Tx`t!dp?>5Pfbhc*!*wzfWkj_x`Q?`3Jc@9r8uq~dgb+lgeh zlA`eUal3e2ZnWQSSYB>qy#85^>j7!=uO-hG5*erp22NaC81#Ytioc>r?D9$b_JiC+ zSp)8KR$%}FjFNRkeE#c5vKbXNJDBoO< z)73Jt7Y|3v45efud1xkg2GO3OwYfsuBV`f6S_D>Aoh2%=`1Y$bHP>0kBvTSowX57H z&1nbbx=IT>X^ScKYL&&{LNq~^UNgR|at`D;SxTYpLvnj_F*bGgNV2tEl1k$ccA&NW zmX(LV*>Op)BOgoric(98mIU)$eUa&jM5bKlnOrHm$p^v@u;W0J)!@XWg+#X=9En(-tiw!l?65rD=zzl(+%<)bI{ZN;SRco{jO;>7 zlSY|TIxuN|d#YHx^^~>iYj2V>cC>wQwWzGVI!6#epjJ6tl_`7tDY17WMKMB@s*Jr& zXOs*@>EwQ6s>M13eZEBJ#q0|;8jao{wK4keesH9?$OSk~_3#*x`8fAzQa7fprQ6(Z zi$}B%m81y*S)RxaX;wW!5{{EDw8)IE3XDRO1Y^%TMr}c|Y>WBAKT=b*K&uMT(?JSl zO>gVtl_bKQ$??TeWr7wYO+Vbl?CTQj?JrW&td`|#@;R2Gca9jq^p`{@)KY97o3}Af zfTh{pUUWD;P7sq=I!lA6;*hq0Nq`F56T)x$K?BMOk}tptYw(%$?*otp2N6IF3#GgqM46Cda!qzvGZcMgcGV`bY5ZIfOB6^;US#WgRai zq#vS8ZqPY953|eFw<-p2Cakx|z#_{4pG}mk{EANI{PnK*CUslvS8whko=OTe13|It z>{O2p=mmanR2-n>LQHaMo}noWCmjFO@7^z~`Y{V>O`@rT{yBS=VXsb}*Pi_zDqM3? zjCZqWR}fEzAkms+Hiq8~qRAFvo}dVW{1gcZ?v&PdX?UG*yS}zT9g7nZ!F1WRH}sHA zJ4~B2Br~8?uhbaX!3g+7=3fVM)q^wEzv**rk5e34==NRCV z3G$G5B!DICFslm)c){oesa_0muLxGoq`xYVNURl*NhE#v2>y9vDz&vJwrB`Q>DhN# zY2GnY!Y^8E%PU0}haXL$8a5QN1-&7NWuC~{62j| z2ozmFyx8GpOzj?&KK1JF28;E8H_p4N^LMm9K0y}!lCxcK79eFGTtGm?7jy?t94Q@X zli|our1#|>f*68fyA0bSn=YisYSl8HB(dFN4Y$qb7p4DR0YQt=^eEMnJkgiM48$>QV6x5*^a|D|t zMPDk}u<^YEYrt|H&hy)DRk%rDIb{LTo;h7=fp^J9Lr&`{9`8_pS*tQ_$KXB$2#5{h z-&yPbN-zInq{7aYZuaItS8-2Mb4OQe2jD*&)0~898E|HlAq`o!M&It@vvnj z_y@))>~_oR%S8OfmFTGYIat^#8_YKMqWLac<^}RZFDcJqvSJa>&6HaLS7p-$)QyL= zHrO|t75`d41Bp37RZtKR%g^%o@9C5Ce=CjuvVQ-KI#Uw2WWa>cho;jztUt~Le*_pT zkfA2iif9QFp;vhd)|A?tdAQ?9o~?EqgL;=)eKFQ{E^u?OIP}fl^5A;$^ZVutCIqj5 z&*i+G?!Px|5~~6zTYf>~uw*kM`5p&Hju&#w!7^An3*mQwTK22wC7p^OsvMjWf`$MY zLX|ZFV#+>Uq2!QyRD9cgbI9nswteMAMWtK(_=d%r?TLrx?_rkjbjI(rbK#T9Gn}J| z5ajow3ZErpw+%}YfVL-q^{r~##xJ^_ux2yO1!LJZXg)>F70STV=&Ruwp&XP^_?$h0 zn>$a?!>N+Kt$UXzg`e+szB}*uw)Z$uL6?>*!0IrE)SgV~#a?Qgg7HuTsu3ncrcs|l z=sQSMtr}S!sQ4SriKg=M`1Y|bC`XJ+J(YT)op!Q);kj0_e)YNVNw8SI|1f%9%X?i5>$lLE(Wfc$wY?(O985d5e*)UPtF!7gG3(Kd z-^=-%-wWCEK`r4oFh^{|;Ci%W^P>K%9dBNDqi%c$Q{iY#(zbwN7~pQI=SHd%WuV7Z zO?0P;Zc6yeN;)IbJIP0=>W)EgE!76jM^?IyQ*D(T})1NGmP z~YAb6T^#R6;)Ls;cV~LWk z33lcLpbSjxStw9Z>Nv&+rPOXxCGB=?ttZs?{OF7;GYlV&w7-82POb$XrogqFpLA2`j&MLZXr=IG>PAFSb2np~x;E_kV{ zsDwbK$?iYRn7$;mHYZhQn6P2#_hXAHd?;q~!Zy}%;@%wT3u|Sa-!WxxOE_fwyFv*Db@>X;Rl+fK1oP?55*dN0#2%SuikZ)y7Kx>`8*9d?}5 zKvXF7J5&Ey6{A8qUFxrFOh<$xdSWV^dw7z|`7RVZJhAwO72V zRrM_3*wI`^ycl7~>6KaCYBr#WGR>}B)Q(V%&$MhVrU>u~ql zjGeZF&>=_ld$oY!V}5}Gb> z*iP38KOav9RHY)0uITwgz99w- zJX-0BGCdY*$c7pi@>@-`2>#>}c(DHaI62ntpKz z`c01Z#u7WuMZ71!jl7hv5|o61+uv5nG?*dffEL~328P5HlKh2&RQ;9X@f>c1x<>v= zZWNSz3Ii~oyAsKCmbd}|$2%ZN&3gc9>(NV=Z4Fnz2F@)PPbx1wwVMsUn=-G=cqE3# zjY{G4OI~2o$|*iuswTg1=hcZK$C=0^rOt-aOwXuxU=*uT?yF00)6sE}ZAZyy*$ZTH zk!P*xILX#5RygHy{k?2((&pRQv9_Ew+wZ>KPho_o1-{~I*s1h8 zBse@ONdkk-8EG?r5qof}lwTxdmmEN|%qw(STW|PFsw1LD!h_Vjo;C4?@h|da4Y;*; zvApQ=T&=jWU39Uz=_yN@Bn0{{)yn8RZ2&X!<*KBv-7tcWdkF1Ij8D0mU zwbcs}0vDaLGd@xx%S_QZ1H)GTt`~>+#z}HXJTl9S!sd9seVJc|_wUMSdD$>k`K_RG zlq(fsnR@KM^;C}}&vG2t+}_nGPuI5ovg$6TYeMPIREGxP@2r~RKd@>gV`mq0XENsh z%IRZ-ZNP+4#J`o-yRpP;w@;CrSr3wiix3e9Qc|s(WapRq950P->g|JYC$A)$YrGeH zz5dKlAHAPJ>%?llqqB&#+#VU3sp=9>Xms1J;tSYN>LMwNtU68yr!})K4X>%^IrIDp z>SHy&6fJHybwS^BW>okFeaQp6wxaVP`hy;ZX#e+=w3c?PGD&_LmeqL8oZ*YaM1+#S z5WNAKo4+99JW(+qcMjh;+c%R#R?t;(aQ`2`C=bo((ERzgAwKKazXy*0wHN;v;P|f> zBW&?`h#_I^?Bc5GX7XP@|MOiw%&-#?EQ|w+FdCl_&qPN&s$|Z17UCF9oXS#N z)px6>zm&}0osTnCGI;AXsj`q=LpIsW4x}q~70uey5N_NpdJ*Gv^@$g@f2{EB>LP7Y zE5P`jZh1vHNgk7LfMT({jLCjRZa4ubW;UA#%<@Zj?efrPdm{W3J5UEFgm`YkVqz;AMFetZuM5uQpvORb1GDX`WZGwTrF z46+&sAri5QXCfGYpdgonWR5`>ZEa;?jrKvfNvXF<&l)1uU-3q#4X16R2~?P0yg3H` zfw82QWZo^cac+%(g^_6`+2>~Fvy{pOCGnj86+=-!N`GPWAjus1ejhn6f4|mDkU6EE z&u~;xfdRMkj=h;4d~~+4(>L8weT3cz9e@E11EH!tX<IC!@kS+dsIQA`HQ2vdoS zzSD0U?mb1M0@qXu{yhZk2Y6}2B-AvvYg|tRr6z*_*2l*VLiR6G;M{O^Znq~LI%=I_ zCEU{htx&Bo+69G`p|A@R>KlY1*;;!{aWq?Pc0Cu!mT-0S`!>3<@s%Ri;utYNQ+CXDj+LC5<*$4*$-mogGg^S~3JRv{ry zPJzKJg!XKb>P}yJVc^1V@T&MV{z;@DLhvV{dG?RogCcPkROivliSr58>5Zw&&A2?n z9`JOLU;eQGaOr6GB(u{t3!+$NaLge$x#M&*sg!J;m~rRc)Ij5|?KX_4WiM-eE%t8e zqUM7eZ~ZonavR;K4g2t$4Fj=UVyEHM7LPb%8#0?Ks{~?!qhx9)2^>rg8{0npLtFKR zJB)19TFiD^T7IUXA8wt!@n5gj&@OK~EO}MR6^qd?^-?%-0~b2K9RWh+_mSEQQWsLCFOt#JlAQMgNxvv-m z;sF*r;WZ*Wi@I|6pMN+|_rLYKlWwvpKZY9rA;fo8l8hFQGI?4#kt1-r4UL;nPF@{~ z2T~a@2>yD|GuU55boxoIIe_BFo2Vq&rs&2itv|B>OC*bIeOqMBRw~y5KRMwiVHc)` zIBdliiY?Ai7*+k#NZf3MW5!hya~RZ6r7k)b?HF0e(n`ZX=iCpT7St`FDwL@SGgKlq zNnnU*3IcnYDzJg{7V$cb`xeb4(s(({&%f69XMTw-JQErS%?X_}?&y&tvHw@>1v{#R z4J@(=el^kRI+jGa;4)l#v%-jM^$~0ulxh6-{w*4Lsa>Tuc z>ElR3uM~GUChI)c{TW${73A3$vs<&iH;e?4HjW2MvSz9tp9@69+`_@x{Qte^eFo5IlAi&zw$=t6u8K%8JtjRI88PFNM7R>DaCO3rgngmk zI-RMOyt@kr-gVra=tl^@J#tI7M$dird(?aU!`&1xcm~2;dHN(RCxh4H((f|orQ!BS zu;(3Vn+^doXaqlhnjBJj-)w?5{;EEZTMx+?G>Rp4U^g<_yw_blAkdbj=5YrNhZB9@ zNmW=-!yFx5?5aF^+6*1XI|s3lIn_eyh`uv%?liNzSC#z&z^R(mqEYL@TdWzgkf>g1 zedzs*={eJavn{8vF%4nf@et<@wkOPR>NiVuYtESbFXQ;sDz_;|ITVeoW|me5>jN5P z5--{13JT{3ktkAf9M;Jty)yectg#{+9sK{C;2CvPU81tB3{8S5>hK{EXdVe?fR?sd8m`V zPM*$)g$HKp0~9Xf6#z!YJ&g!%VkCMxkt>ofE!62?#-&%|95^)JJ9 zk;GlJdoH0HwtDF(_aTv}mt$?EyRyE6@pm5DG~Gj-2%3HcZT13e)$)z99bdK_WCx|Q zQNza(R)Z>ZKTn8oIdcw%c^pFaMpFZ4HOds!BODgSBWJJYW3I_WJvoEm4xsfs%#LZ6 zdPCk{5XJ>2f7Hj-i*9lTW6BKCIuy)3L!b3(uPoSgW1WA+OEYYBRgSsJq7wjHh%c8ymMs3FU%~cprqL*084p*^T3{J%Gwq`jB30n(&y6- zII8-_r-s5&CVtsoNZ9%On?7yn;oZG03-$wx^uRk9>b*ufh15|HHk|%=MA^ioyb9CYU$7y$4R|M5HvpiCTxKSU`LUg$+ zB3IBl&{qO}agqF~BFM6&11wMeR-#Rkuh_(^j+P4{;X_w|siva$5P`dykyhfAUD%e8 z+{G0|7(Q`_U91sMKFO^rHoCWfXi0$^ev)-187G}klYv@+Rf%uZ&T4-Uhh=)pcU6O1 znXc^c5)!$X+39|4`yNHuCj0wkm+K1VN0G3_EL?-ZH$p5Y*v6ec4MV zS~1~}ZUhl&i^4`Fa|zyH4I%rXp;D6{&@*^TPEX2;4aI$}H@*ROEyFfe^RZI%;T>X> z>WVSUmx@2gGBxkV&nfyPK=JI$HxRKUv(-*xA_C;lDxT|PgX*&YYdkrd5-*3E1OSXBs>35DLsHHp%zm+n0N(Yu{lMo>_t&d1Xy zfCxl=(CNNx>ze+7w)60mp>(M``Qn$aUrVb$cJAb6=Do7VgW`Qn2;v5{9tB)jP$_mB zn{Hb_sMs4yxK|!`PI7+zO68}{Iv)dpu!+ZZl)xuoVU(oFsm<3gT{j2c*ORl|Lt+?dR^M?0 znW6rNA)cR*ci;z?BaG(f(XynY_y+kTjj~T$9{N{>ITQ4-DmZ6{cOkoea9*LpYL{Apo0hSpLqJu z9`tjP&ei;%pn9QY>-$9=<73M#X;qGb+%Bt0x>=u`eDtthI+LWB9CdAO=ulZo9&Ohs2X8GW>b7#&U|py28KTvPBl#Nqv^{AgkVXrOyS z@%3)}$I&mJOYWoG$BBb)Kb~0ptDmBxHNH^i6B8FA7NR2HfTnjP?eDnoY4NS_aYg4P zGGPw11sAf^^fTkY#j@T#6Ll*^GVaPo-1;aS6_a}{r{tWZilzse2m zc?LS=B|EWxCD|!O%|%t3C@Rd7=rKJRsteAWRoDu|*Kx-QwYZQeYpGrZ_1J%mFM;*S*u=0 z%1OC9>kmCGqBBu#-1jVPRVW*BTv%3uPI8fO?JOZD#P_W^V+K7&KVB>hzZ@PdY*%Ezo;}|5Mk`Mo2m*_K%no*jDJGp(s9j;&U`Z>z zO#SEe)k!p$VE-j2xDoX$!;Up5%8x$c`GH$l+gTA*YQaE0jwCOA<*__2NkV){z_u2=4NQ zSk$(oj$%ygio?3V8T3IyGMYvPs`t{im2IoHs7or+>>MYvG%Q?PwOLqe%73uGh6Wn; zo>e7qI$9?%cVVkvQLOLKcU5n*`~qn8pzkdu=Z4#2VnhUy>S*;kT=NqA!dQtnE?wVg zOKobxJ|QCjk`!(2*~5NQx{{=Lr=)ndyn{V|&PxUa=xQXVU?#M24F8H%C*uvs(#Va0 zSkp}0EFYq0#9xp&$O?gIInc#^^_6Ol88W%)S5A@HeE0(SR&!Yl>u=*5JEoUViDR@2 zJBjTsp=Y44W`Nb2+*CcZCkwP(QChX1s)b09DEIZCKt1$q2~;&DJ9!{bQ1Y6&T_9u1 zZM8^im8Wf#FUO6tZqc7#`z0cN_JA>#U_b7he%?cCnlV2&47y5Fc)Z7bp5xGe1zNq9 zl1VaV-tsm3fY=oIX^SPl!P;9$o?**0brq#ShM~3CXhh^SK0oOKB9O>;q3G@ z&4&h$mLSgohc^5IC|H>IGfZvVQFUT>T$|U7{znY`56<5d)07oiv*2R0+-BGPPkWJ! zIOzKF+<5o2YLWP|SGCx8w@<>u6K1o`++xJ+6kaJrt<&0Haq zyUccgxI$sR07Vo9-pF);heBva;?&NcAzC*gSSG9B3c?A;IH9J zl$j%F4*8;F0;H2Cjo*kWz4{kSh?nX}23&&KL+U(#nOAuR`wn@uwUNkWEgb*ZShKPy z`aXTJT4f*Um4`iv2KOfzf-~`#pOfH8>is*xnLBDTyx2Xuc8Y2Od6z((P2AZK@b_96 z#0V6jdw>sEDJ#uNGV|EshD1g&bYZCzCZTZ)286HLHc8Eyy_HPi;d#%;Wx}d6tUUxq z_VB$+898z_{9-A<*v6VI7?(dC04o!8$>DQ$OdbrA_@<6auiBNp{Dw$Hs@@gcybIQT zAU7Pc5YEX&&9IZ~iDo&V`&8K$-4o$)g?wF8xdv1I8-n}1bc7tviIBqt z#iIl1Hn;W?>2&#bU#VZ1wxq(7z=Q15#0yoz)#|r`KSPKI-{aN%l61^?B4RMDt?Vk` z)G#K6vUN?C!t{Q<@O4$0(qI>$U@@TI2FVF;AhSSb5}LtXx&=k&8%MWM3wv;Xq0p~W z#ZX;QFv5G9-i6=+d;R7Dwi)ciIZ1_V!aw;K^etau+g0fOA2HXpV#LQZGzf?h#@}(o z|3w!sZ|&mp$;tmDiO=zef5C|Alz+@@4u5#yZ7yNpP=&`432%a{K#{;nsS!jwk-$Qs zZRty}+N`Y~)c8|$&ra{bOQWM2K7qa}4Y{ndK%dKp&{ zFCvX{PAy_C{xzS_-`0>JlPP7&5!5 zBQ$NQz^z#2y-VeIxnfY|RzU`w+1t6vwQ|wM)LlpuaUzYehGII;>2DYyR|~wC@l97s zgX=f*1qtfDyco%BHmN+o<2qoi`D67R+RM$$NN5-moE4kx3MCFfuip*45nComOZKQf z3!(8tkSdhY5+A%@Y=eVEZkXU3S6B2V-R$ZuRIXWhsrJg3g)p4vXY@RV60bKuG zT6T!enE<;(A{*HPQhae*(@_!maV~AWD4EOwq10tkCXq+HPoe_Pu?d4Kg=2ypcs?&f zLa>mEmPF4ucJ%i~fEsNIa{QmQU27%Abh|w(`q)s~He5$5WYQ_wNJX6Qop<=7;I1jd zNZak`}0lVm+^O!i;|Lwo}ofXuJ)*UtH4xaPm*R7?YS*<&D__=@Kki>{f_Z-XqM;Tj195+~@d;rx zh5pj8oMuupWa#E(%85**I~1Zat-Sa^_R11-CiKdd`8m(DGuzOm9lX$Dd!DX!_Al}d zS!-|}dWG80S;`jSKDH%Uv;-OJNeBI0Bp$z->{_>1KU%h&Af7nns(L=xRN1 zLvOP=*UWIr)_5G2+fCsUV7mV|D>-~_VnvZ3_>=9 z_bL6`eK%W*9eJ34&Puz^@^ZIyoF@%DTun#OOEdUEn8>N9q(}?5*?`o?!_<(i%yc`k zf!xXD6SQscHgPgiHt>x6{n{+}%azrfV4VHi#umyi0;11c816`E??2`$;Rc`)qA2H( z5L|{o=ut7Te=^~@cR0_#cah0?w0Me$&>}ga8xxy=?DDl#}S~Y z4o2n`%IyGjQEP%8qS|v(kFK&RCJbF1gsRVJ>ceSjU`LuYJu%C>SRV#l`)ShD&KKzv ztD<9l0lcW0UQ8xjv|1NXRrCZhZh3JFX_BNT@V|u9$o~8M=cjOX|5iBS|9PAGPvQLc z6sA~BTM(~!c&V=5<}ZIx}O7A;|&bd7vR_y)t+ z?Vm7kb^gJ88g;!fRfMTSvKaPozQz4WcYD8l#0WxQ${P%0A$pwhjXzyA0ZzErH{1@M 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 OJOEd-=rxTO#Qy`$*1Hh^ literal 0 HcmV?d00001 diff --git a/spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.properties b/spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..c954cec91c --- /dev/null +++ b/spring-jenkins-pipeline/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip diff --git a/spring-jenkins-pipeline/README.md b/spring-jenkins-pipeline/README.md new file mode 100644 index 0000000000..7e562664e6 --- /dev/null +++ b/spring-jenkins-pipeline/README.md @@ -0,0 +1,23 @@ +BASIC CRUD API with Spring Boot +================================ + +This is the code of a simple API for some CRUD operations build using Spring Boot. + +### Requirements + +- Maven +- JDK 8 +- MongoDB + +### Running + +To build and start the server simply type + +```bash +$ mvn clean install +$ mvn spring-boot:run -Dserver.port=8989 +``` + +Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) + +Enjoy it :) \ No newline at end of file diff --git a/spring-jenkins-pipeline/mvnw b/spring-jenkins-pipeline/mvnw new file mode 100755 index 0000000000..a1ba1bf554 --- /dev/null +++ b/spring-jenkins-pipeline/mvnw @@ -0,0 +1,233 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + 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 + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} "$@" diff --git a/spring-jenkins-pipeline/mvnw.cmd b/spring-jenkins-pipeline/mvnw.cmd new file mode 100644 index 0000000000..2b934e89dd --- /dev/null +++ b/spring-jenkins-pipeline/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% \ No newline at end of file diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml new file mode 100644 index 0000000000..1c35f0f73b --- /dev/null +++ b/spring-jenkins-pipeline/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + spring-jenkins-pipeline + 0.0.1-SNAPSHOT + jar + + spring-jenkins-pipeline + Intro to Jenkins 2 and the power of pipelines + + + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-5 + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + + + + integration + + + + maven-surefire-plugin + + + **/*UnitTest.java + + + + **/*IntegrationTest.java + + + + + + + + + unit + + + + maven-surefire-plugin + + + **/*IntegrationTest.java + + + + **/*UnitTest.java + + + + + + + + diff --git a/spring-jenkins-pipeline/src/main/java/com/baeldung/SpringJenkinsPipelineApplication.java b/spring-jenkins-pipeline/src/main/java/com/baeldung/SpringJenkinsPipelineApplication.java new file mode 100644 index 0000000000..fcf4fde414 --- /dev/null +++ b/spring-jenkins-pipeline/src/main/java/com/baeldung/SpringJenkinsPipelineApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@SpringBootApplication +@EnableMongoRepositories +public class SpringJenkinsPipelineApplication { + public static void main(String[] args) { + SpringApplication.run(SpringJenkinsPipelineApplication.class, args); + } +} diff --git a/spring-jenkins-pipeline/src/main/java/com/baeldung/domain/Student.java b/spring-jenkins-pipeline/src/main/java/com/baeldung/domain/Student.java new file mode 100644 index 0000000000..3d1dd27b0e --- /dev/null +++ b/spring-jenkins-pipeline/src/main/java/com/baeldung/domain/Student.java @@ -0,0 +1,73 @@ +package com.baeldung.domain; + +import javax.validation.constraints.NotNull; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.io.Serializable; + +@Document(collection = "STUDENT") +public class Student implements Serializable { + + @Id + private String id; + @NotNull + private String firstName; + private String lastName; + @NotNull + private String phoneNumber; + private String email; + + public Student(String firstName, String lastName, String phoneNumber, String email) { + this.firstName = firstName; + this.lastName = lastName; + this.phoneNumber = phoneNumber; + this.email = email; + } + + public String getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public String toString() { + return "Student{" + + "firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", phoneNumber='" + phoneNumber + '\'' + + ", email='" + email + '\'' + + '}'; + } +} diff --git a/spring-jenkins-pipeline/src/main/java/com/baeldung/repository/StudentRepository.java b/spring-jenkins-pipeline/src/main/java/com/baeldung/repository/StudentRepository.java new file mode 100644 index 0000000000..d0ca7d8510 --- /dev/null +++ b/spring-jenkins-pipeline/src/main/java/com/baeldung/repository/StudentRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.repository; + +import org.springframework.data.mongodb.repository.MongoRepository; +import com.baeldung.domain.Student; + +public interface StudentRepository extends MongoRepository { +} diff --git a/spring-jenkins-pipeline/src/main/resources/application.properties b/spring-jenkins-pipeline/src/main/resources/application.properties new file mode 100644 index 0000000000..b6bfd8f6f3 --- /dev/null +++ b/spring-jenkins-pipeline/src/main/resources/application.properties @@ -0,0 +1,14 @@ +# the db host +spring.data.mongodb.host=localhost +# the connection port (defaults to 27107) +spring.data.mongodb.port=27017 +# The database's name +spring.data.mongodb.database=Jenkins-Pipeline + +# Or this +# spring.data.mongodb.uri=mongodb://localhost/Jenkins-Pipeline + +# spring.data.mongodb.username= +# spring.data.mongodb.password= + +spring.data.mongodb.repositories.enabled=true \ No newline at end of file diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java new file mode 100644 index 0000000000..dd8a234d1d --- /dev/null +++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java @@ -0,0 +1,37 @@ +package com.baeldung; + +import com.baeldung.domain.Student; +import com.baeldung.repository.StudentRepository; +import org.junit.After; +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.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +public class SomeIntegrationTest { + @Autowired + private StudentRepository studentRepository; + + @Before + public void setup() { + Student student = new Student("Paul", "Smith", "64377473774", "me@mymail.com"); + studentRepository.save(student); + } + + @Test + public void testDB() { + long count = studentRepository.count(); + + assertNotEquals(0, count); + } + + @After + public void clean() { + studentRepository.deleteAll(); + } +} diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java new file mode 100644 index 0000000000..ea317ed7cd --- /dev/null +++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java @@ -0,0 +1,11 @@ +package com.baeldung; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class SomeUnitTest { + @Test + public void init() { + assertEquals(1, 1); + } +} diff --git a/spring-jmeter-jenkins/README.md b/spring-jmeter-jenkins/README.md index 49c18122a2..dec8364647 100644 --- a/spring-jmeter-jenkins/README.md +++ b/spring-jmeter-jenkins/README.md @@ -1,20 +1,7 @@ BASIC CRUD API with Spring Boot ================================ -This is the code of a simple API for some CRUD operations realised for a seminar at [FGI](www.fgi-ud.org) using Spring Boot. - -### Demo -* API: The online version **is**/**will be** hosted here: https://fgi-tcheck.herokuapp.com -* Mobile version is also opensource and located here: https://github.com/valdesekamdem/tcheck-mobile - -### Features -#### Currently Implemented -* CRUD - * Student - -#### To DO -* Validations of input with: [Spring Data Rest Validators](http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html) - +This is the code of a simple API for some CRUD operations build using Spring Boot. ### Requirements @@ -49,7 +36,6 @@ Or create a new one via a POST: $ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "lastName" : "Orleando", "phoneNumber": "+237 545454545", "email": "mymail@yahoo.fr" }' localhost:8080/students ``` - Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) Enjoy it :) \ No newline at end of file From eb33074a0ee4a31c538e4523367a80a9c3c63cc6 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 29 Nov 2017 05:30:56 +0100 Subject: [PATCH 21/36] Simulate false unit test --- .../src/test/java/com/baeldung/SomeUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java index ea317ed7cd..1e0fc985c3 100644 --- a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java +++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java @@ -6,6 +6,6 @@ import static org.junit.Assert.*; public class SomeUnitTest { @Test public void init() { - assertEquals(1, 1); + assertEquals(1, 0); } } From 3d49c4a4b6d5c7eeeab9f5203701b19e198873b4 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 30 Nov 2017 04:58:55 +0100 Subject: [PATCH 22/36] Disable failded build for unsuccesful test --- spring-jenkins-pipeline/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml index 1c35f0f73b..5ebc7540d6 100644 --- a/spring-jenkins-pipeline/pom.xml +++ b/spring-jenkins-pipeline/pom.xml @@ -50,6 +50,13 @@ maven-checkstyle-plugin 2.17 + + org.apache.maven.plugins + maven-surefire-plugin + + true + + From 138e7fd492bbd611603ef2423c272a260563a2e8 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Thu, 30 Nov 2017 05:52:28 +0100 Subject: [PATCH 23/36] Let the build failed if the test is not Ok --- spring-jenkins-pipeline/pom.xml | 7 ------- .../src/test/java/com/baeldung/SomeUnitTest.java | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml index 5ebc7540d6..1c35f0f73b 100644 --- a/spring-jenkins-pipeline/pom.xml +++ b/spring-jenkins-pipeline/pom.xml @@ -50,13 +50,6 @@ maven-checkstyle-plugin 2.17 - - org.apache.maven.plugins - maven-surefire-plugin - - true - - diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java index 1e0fc985c3..ea317ed7cd 100644 --- a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java +++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeUnitTest.java @@ -6,6 +6,6 @@ import static org.junit.Assert.*; public class SomeUnitTest { @Test public void init() { - assertEquals(1, 0); + assertEquals(1, 1); } } From 235ea3eb782e2bc2ba3587cbc836268263d7d294 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Fri, 1 Dec 2017 06:31:30 +0100 Subject: [PATCH 24/36] Formating --- .../src/test/java/com/baeldung/SomeIntegrationTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java index dd8a234d1d..092ebb93fd 100644 --- a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java +++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java @@ -9,7 +9,8 @@ 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.SpringJUnit4ClassRunner; -import static org.junit.Assert.*; + +import static org.junit.Assert.assertNotEquals; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest @@ -19,12 +20,12 @@ public class SomeIntegrationTest { @Before public void setup() { - Student student = new Student("Paul", "Smith", "64377473774", "me@mymail.com"); + Student student = new Student("Paul", "Smith", "64377473774", "me@mailprovider.com"); studentRepository.save(student); } @Test - public void testDB() { + public void whenInserting_andCount_thenWeDontGetZero() { long count = studentRepository.count(); assertNotEquals(0, count); From c067162a5676a59fb8f2b9520111e6fb14a15991 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Tue, 5 Dec 2017 05:29:10 +0100 Subject: [PATCH 25/36] Jenkins pipeline script for unix and non-unix OS --- spring-jenkins-pipeline/pom.xml | 3 +- .../scripted-pipeline-unix-nonunix | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 spring-jenkins-pipeline/scripted-pipeline-unix-nonunix diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml index 1c35f0f73b..9b4727a235 100644 --- a/spring-jenkins-pipeline/pom.xml +++ b/spring-jenkins-pipeline/pom.xml @@ -21,6 +21,7 @@ UTF-8 UTF-8 1.8 + 2.17 @@ -48,7 +49,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 2.17 + ${checkstyle.version} diff --git a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix new file mode 100644 index 0000000000..861c38c8a2 --- /dev/null +++ b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix @@ -0,0 +1,91 @@ +node { + stage 'Clone the project' + git 'https://github.com/dassiorleando/tutorials.git' + + dir('spring-jenkins-pipeline') { + stage("Compilation and Analysis") { + parallel 'Compilation': { + if (isUnix()) { + sh "./mvnw clean install -DskipTests" + } else { + bat "./mvnw.cmd clean install -DskipTests" + } + }, 'Static Analysis': { + stage("Checkstyle") { + if (isUnix()) { + sh "./mvnw checkstyle:checkstyle" + + step([$class: 'CheckStylePublisher', + canRunOnFailed: true, + defaultEncoding: '', + healthy: '100', + pattern: '**/target/checkstyle-result.xml', + unHealthy: '90', + useStableBuildAsReference: true + ]) + } else { + bat "./mvnw.cmd checkstyle:checkstyle" + + step([$class: 'CheckStylePublisher', + canRunOnFailed: true, + defaultEncoding: '', + healthy: '100', + pattern: '**\target\checkstyle-result.xml', + unHealthy: '90', + useStableBuildAsReference: true + ]) + } + } + } + } + + stage("Tests and Deployment") { + parallel 'Unit tests': { + stage("Runing unit tests") { + if (isUnix()) { + sh "./mvnw test -Punit" + + step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) + } else { + bat "./mvnw.cmd test -Punit" + + step([$class: 'JUnitResultArchiver', testResults: '**\target\surefire-reports\TEST-*UnitTest.xml']) + } + } + }, 'Integration tests': { + stage("Runing integration tests") { + if (isUnix()) { + sh "./mvnw test -Pintegration" + + step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*IntegrationTest.xml']) + } else { + bat "./mvnw.cmd test -Pintegration" + + step([$class: 'JUnitResultArchiver', testResults: '**\target\surefire-reports\TEST-*IntegrationTest.xml']) + } + } + }, 'Deployment': { + stage("Staging") { + if (isUnix()) { + sh "pid=\$(lsof -i:8989 -t); kill -TERM \$pid || kill -KILL \$pid" + } else { + bat "FOR /F 'tokens=5 delims= ' %%P IN ('netstat -ano ^| findstr :8989') DO TaskKill.exe /PID %%P" + } + + withEnv(['JENKINS_NODE_COOKIE=dontkill']) { + if (isUnix()) { + sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &' + sh "while ! httping -qc1 http://localhost:8989 ; do sleep 1 ; done" + sh "curl http://localhost:8989" + } else { + bat 'start ./mvnw.cmd spring-boot:run -Dserver.port=8989' + // Here we need to check(loop) if localhost:8989 is up + // Once it's we continue de script + bat "curl.exe http://localhost:8989" + } + } + } + } + } + } +} \ No newline at end of file From 1e0f0c1849036b6403629911e1e21212950079ba Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Tue, 5 Dec 2017 07:51:37 +0100 Subject: [PATCH 26/36] BAEL-1408: Intro to Performance Testing using JMeter --- spring-jmeter-jenkins/pom.xml | 21 +++++++++++++++++-- .../resources/20171205-JMeter-Jenkins.csv | 6 ++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv diff --git a/spring-jmeter-jenkins/pom.xml b/spring-jmeter-jenkins/pom.xml index 38b5f98e45..dcf1c6d3e5 100644 --- a/spring-jmeter-jenkins/pom.xml +++ b/spring-jmeter-jenkins/pom.xml @@ -21,6 +21,7 @@ UTF-8 UTF-8 1.8 + 2.6.0 @@ -45,8 +46,24 @@ org.springframework.boot spring-boot-maven-plugin + + + com.lazerycode.jmeter + jmeter-maven-plugin + ${jmeter.version} + + + jmeter-tests + + jmeter + + + + + ${project.basedir}/src/main/resources + ${project.basedir}/src/main/resources + + - - diff --git a/spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv b/spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv new file mode 100644 index 0000000000..719fc18f41 --- /dev/null +++ b/spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv @@ -0,0 +1,6 @@ +timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect +1512454361862,181,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 181 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,181 +1512454361926,116,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 116 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,116 +1512454361862,181,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 181 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,181 +1512454362126,2,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,,2058,0,1,1,0,0,2 +1512454362326,2,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,,2058,0,1,1,0,0,2 From 0d37e8831602fadff7816174f5a4bbc11f262514 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Tue, 5 Dec 2017 18:45:09 +0100 Subject: [PATCH 27/36] Fix indents --- spring-jenkins-pipeline/pom.xml | 174 ++++++++++++++++---------------- spring-jmeter-jenkins/pom.xml | 118 +++++++++++----------- 2 files changed, 146 insertions(+), 146 deletions(-) diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml index 9b4727a235..071f6e6e36 100644 --- a/spring-jenkins-pipeline/pom.xml +++ b/spring-jenkins-pipeline/pom.xml @@ -1,98 +1,98 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - spring-jenkins-pipeline - 0.0.1-SNAPSHOT - jar + spring-jenkins-pipeline + 0.0.1-SNAPSHOT + jar - spring-jenkins-pipeline - Intro to Jenkins 2 and the power of pipelines + spring-jenkins-pipeline + Intro to Jenkins 2 and the power of pipelines - - parent-boot-5 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-5 - + + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-5 + - - UTF-8 - UTF-8 - 1.8 - 2.17 - + + UTF-8 + UTF-8 + 1.8 + 2.17 + - - - org.springframework.boot - spring-boot-starter-data-mongodb - - - org.springframework.boot - spring-boot-starter-data-rest - - - org.springframework.boot - spring-boot-starter-test - test - - + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${checkstyle.version} - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + + - - - integration - - - - maven-surefire-plugin - - - **/*UnitTest.java - - - - **/*IntegrationTest.java - - - - - - + + + integration + + + + maven-surefire-plugin + + + **/*UnitTest.java + + + + **/*IntegrationTest.java + + + + + + - - unit - - - - maven-surefire-plugin - - - **/*IntegrationTest.java - - - - **/*UnitTest.java - - - - - - - + + unit + + + + maven-surefire-plugin + + + **/*IntegrationTest.java + + + + **/*UnitTest.java + + + + + + + diff --git a/spring-jmeter-jenkins/pom.xml b/spring-jmeter-jenkins/pom.xml index dcf1c6d3e5..daef45b6d4 100644 --- a/spring-jmeter-jenkins/pom.xml +++ b/spring-jmeter-jenkins/pom.xml @@ -1,69 +1,69 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - spring-jmeter-jenkins - 0.0.1-SNAPSHOT - jar + spring-jmeter-jenkins + 0.0.1-SNAPSHOT + jar - spring-jmeter-jenkins - Run and Show JMeter test with Jenkins + spring-jmeter-jenkins + Run and Show JMeter test with Jenkins - - parent-boot-5 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-5 - + + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-5 + - - UTF-8 - UTF-8 - 1.8 - 2.6.0 - + + UTF-8 + UTF-8 + 1.8 + 2.6.0 + - - - org.springframework.boot - spring-boot-starter-data-mongodb - - - org.springframework.boot - spring-boot-starter-data-rest - - - org.springframework.boot - spring-boot-starter-test - test - - + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - + + + + org.springframework.boot + spring-boot-maven-plugin + - - com.lazerycode.jmeter - jmeter-maven-plugin - ${jmeter.version} - - - jmeter-tests - - jmeter - - - - - ${project.basedir}/src/main/resources - ${project.basedir}/src/main/resources - - - - + + com.lazerycode.jmeter + jmeter-maven-plugin + ${jmeter.version} + + + jmeter-tests + + jmeter + + + + + ${project.basedir}/src/main/resources + ${project.basedir}/src/main/resources + + + + From e5c9d8144b1a49107c49c8a7d165c41b1af81c02 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 13 Dec 2017 04:00:58 +0100 Subject: [PATCH 28/36] Edit jmeter module name --- {spring-jmeter-jenkins => jmeter}/.gitignore | 0 .../.mvn/wrapper/maven-wrapper.jar | Bin .../.mvn/wrapper/maven-wrapper.properties | 0 {spring-jmeter-jenkins => jmeter}/README.md | 0 {spring-jmeter-jenkins => jmeter}/mvnw | 0 {spring-jmeter-jenkins => jmeter}/mvnw.cmd | 0 {spring-jmeter-jenkins => jmeter}/pom.xml | 6 +++--- .../baeldung/SpringJMeterJenkinsApplication.java | 0 .../src/main/java/com/baeldung/domain/Student.java | 0 .../com/baeldung/repository/StudentRepository.java | 0 .../src/main/resources/20171205-JMeter-Jenkins.csv | 0 .../src/main/resources/20171213-JMeter-Jenkins.csv | 6 ++++++ .../src/main/resources/JMeter-Jenkins.jmx | 0 .../src/main/resources/application.properties | 0 ...ringJMeterJenkinsApplicationIntegrationTest.java | 0 pom.xml | 2 +- 16 files changed, 10 insertions(+), 4 deletions(-) rename {spring-jmeter-jenkins => jmeter}/.gitignore (100%) rename {spring-jmeter-jenkins => jmeter}/.mvn/wrapper/maven-wrapper.jar (100%) rename {spring-jmeter-jenkins => jmeter}/.mvn/wrapper/maven-wrapper.properties (100%) rename {spring-jmeter-jenkins => jmeter}/README.md (100%) rename {spring-jmeter-jenkins => jmeter}/mvnw (100%) rename {spring-jmeter-jenkins => jmeter}/mvnw.cmd (100%) rename {spring-jmeter-jenkins => jmeter}/pom.xml (93%) rename {spring-jmeter-jenkins => jmeter}/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java (100%) rename {spring-jmeter-jenkins => jmeter}/src/main/java/com/baeldung/domain/Student.java (100%) rename {spring-jmeter-jenkins => jmeter}/src/main/java/com/baeldung/repository/StudentRepository.java (100%) rename {spring-jmeter-jenkins => jmeter}/src/main/resources/20171205-JMeter-Jenkins.csv (100%) create mode 100644 jmeter/src/main/resources/20171213-JMeter-Jenkins.csv rename {spring-jmeter-jenkins => jmeter}/src/main/resources/JMeter-Jenkins.jmx (100%) rename {spring-jmeter-jenkins => jmeter}/src/main/resources/application.properties (100%) rename {spring-jmeter-jenkins => jmeter}/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationIntegrationTest.java (100%) diff --git a/spring-jmeter-jenkins/.gitignore b/jmeter/.gitignore similarity index 100% rename from spring-jmeter-jenkins/.gitignore rename to jmeter/.gitignore diff --git a/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.jar b/jmeter/.mvn/wrapper/maven-wrapper.jar similarity index 100% rename from spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.jar rename to jmeter/.mvn/wrapper/maven-wrapper.jar diff --git a/spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties b/jmeter/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from spring-jmeter-jenkins/.mvn/wrapper/maven-wrapper.properties rename to jmeter/.mvn/wrapper/maven-wrapper.properties diff --git a/spring-jmeter-jenkins/README.md b/jmeter/README.md similarity index 100% rename from spring-jmeter-jenkins/README.md rename to jmeter/README.md diff --git a/spring-jmeter-jenkins/mvnw b/jmeter/mvnw similarity index 100% rename from spring-jmeter-jenkins/mvnw rename to jmeter/mvnw diff --git a/spring-jmeter-jenkins/mvnw.cmd b/jmeter/mvnw.cmd similarity index 100% rename from spring-jmeter-jenkins/mvnw.cmd rename to jmeter/mvnw.cmd diff --git a/spring-jmeter-jenkins/pom.xml b/jmeter/pom.xml similarity index 93% rename from spring-jmeter-jenkins/pom.xml rename to jmeter/pom.xml index daef45b6d4..977e3bbc94 100644 --- a/spring-jmeter-jenkins/pom.xml +++ b/jmeter/pom.xml @@ -3,12 +3,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - spring-jmeter-jenkins + jmeter 0.0.1-SNAPSHOT jar - spring-jmeter-jenkins - Run and Show JMeter test with Jenkins + jmeter + Intro to Performance testing using JMeter parent-boot-5 diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java b/jmeter/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java similarity index 100% rename from spring-jmeter-jenkins/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java rename to jmeter/src/main/java/com/baeldung/SpringJMeterJenkinsApplication.java diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java b/jmeter/src/main/java/com/baeldung/domain/Student.java similarity index 100% rename from spring-jmeter-jenkins/src/main/java/com/baeldung/domain/Student.java rename to jmeter/src/main/java/com/baeldung/domain/Student.java diff --git a/spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java b/jmeter/src/main/java/com/baeldung/repository/StudentRepository.java similarity index 100% rename from spring-jmeter-jenkins/src/main/java/com/baeldung/repository/StudentRepository.java rename to jmeter/src/main/java/com/baeldung/repository/StudentRepository.java diff --git a/spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv b/jmeter/src/main/resources/20171205-JMeter-Jenkins.csv similarity index 100% rename from spring-jmeter-jenkins/src/main/resources/20171205-JMeter-Jenkins.csv rename to jmeter/src/main/resources/20171205-JMeter-Jenkins.csv diff --git a/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv b/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv new file mode 100644 index 0000000000..92650ea36f --- /dev/null +++ b/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv @@ -0,0 +1,6 @@ +timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect +1513133869106,1150,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 1,150 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1150 +1513133869106,1152,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,"The operation lasted too long: It took 1,152 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1152 +1513133869106,1150,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,"The operation lasted too long: It took 1,150 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1150 +1513133869106,1152,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 1,152 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1152 +1513133869104,1153,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 1,153 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1153 diff --git a/spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx b/jmeter/src/main/resources/JMeter-Jenkins.jmx similarity index 100% rename from spring-jmeter-jenkins/src/main/resources/JMeter-Jenkins.jmx rename to jmeter/src/main/resources/JMeter-Jenkins.jmx diff --git a/spring-jmeter-jenkins/src/main/resources/application.properties b/jmeter/src/main/resources/application.properties similarity index 100% rename from spring-jmeter-jenkins/src/main/resources/application.properties rename to jmeter/src/main/resources/application.properties diff --git a/spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationIntegrationTest.java b/jmeter/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationIntegrationTest.java similarity index 100% rename from spring-jmeter-jenkins/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationIntegrationTest.java rename to jmeter/src/test/java/com/baeldung/SpringJMeterJenkinsApplicationIntegrationTest.java diff --git a/pom.xml b/pom.xml index 8aa9afc6b3..462d70741e 100644 --- a/pom.xml +++ b/pom.xml @@ -177,7 +177,7 @@ spring-integration spring-jenkins-pipeline spring-jersey - spring-jmeter-jenkins + jmeter spring-jms spring-jooq persistence-modules/spring-jpa From 9eb7a54316856c56ec0b3c6d2f980039774e746c Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 13 Dec 2017 04:51:20 +0100 Subject: [PATCH 29/36] Update JMeter tests --- jmeter/jmeter.log | 68 +++++++++++++++++++ .../resources/20171205-JMeter-Jenkins.csv | 6 -- .../resources/20171213-JMeter-Jenkins.csv | 6 -- jmeter/src/main/resources/20171213-JMeter.csv | 6 ++ .../{JMeter-Jenkins.jmx => JMeter.jmx} | 2 +- jmeter/src/main/resources/JMeter.jtl | 43 ++++++++++++ 6 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 jmeter/jmeter.log delete mode 100644 jmeter/src/main/resources/20171205-JMeter-Jenkins.csv delete mode 100644 jmeter/src/main/resources/20171213-JMeter-Jenkins.csv create mode 100644 jmeter/src/main/resources/20171213-JMeter.csv rename jmeter/src/main/resources/{JMeter-Jenkins.jmx => JMeter.jmx} (99%) create mode 100644 jmeter/src/main/resources/JMeter.jtl diff --git a/jmeter/jmeter.log b/jmeter/jmeter.log new file mode 100644 index 0000000000..ce55007e74 --- /dev/null +++ b/jmeter/jmeter.log @@ -0,0 +1,68 @@ +2017-12-13 04:50:16,291 INFO o.a.j.u.JMeterUtils: Setting Locale to en_US +2017-12-13 04:50:16,319 INFO o.a.j.JMeter: Loading user properties from: /Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3/bin/user.properties +2017-12-13 04:50:16,392 INFO o.a.j.JMeter: Loading system properties from: /Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3/bin/system.properties +2017-12-13 04:50:16,406 INFO o.a.j.JMeter: Setting JMeter property: jmeter.save.saveservice.output_format=xml +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: Copyright (c) 1998-2017 The Apache Software Foundation +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: Version 3.3 r1808647 +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: java.version=1.8.0_152 +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: java.vm.name=Java HotSpot(TM) 64-Bit Server VM +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: os.name=Mac OS X +2017-12-13 04:50:16,451 INFO o.a.j.JMeter: os.arch=x86_64 +2017-12-13 04:50:16,452 INFO o.a.j.JMeter: os.version=10.12.6 +2017-12-13 04:50:16,452 INFO o.a.j.JMeter: file.encoding=UTF-8 +2017-12-13 04:50:16,452 INFO o.a.j.JMeter: Max memory =536870912 +2017-12-13 04:50:16,452 INFO o.a.j.JMeter: Available Processors =4 +2017-12-13 04:50:16,461 INFO o.a.j.JMeter: Default Locale=English (United States) +2017-12-13 04:50:16,462 INFO o.a.j.JMeter: JMeter Locale=English (United States) +2017-12-13 04:50:16,462 INFO o.a.j.JMeter: JMeterHome=/Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3 +2017-12-13 04:50:16,462 INFO o.a.j.JMeter: user.dir =/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter +2017-12-13 04:50:16,462 INFO o.a.j.JMeter: PWD =/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter +2017-12-13 04:50:16,466 INFO o.a.j.JMeter: IP: 192.168.10.100 Name: MBP FullName: 192.168.10.100 +2017-12-13 04:50:16,472 INFO o.a.j.s.FileServer: Default base='/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter' +2017-12-13 04:50:16,473 INFO o.a.j.s.FileServer: Set new base='/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter/src/main/resources' +2017-12-13 04:50:17,022 INFO o.a.j.s.SaveService: Testplan (JMX) version: 2.2. Testlog (JTL) version: 2.2 +2017-12-13 04:50:17,134 INFO o.a.j.s.SaveService: Using SaveService properties file encoding UTF-8 +2017-12-13 04:50:17,142 INFO o.a.j.s.SaveService: Using SaveService properties version 3.2 +2017-12-13 04:50:17,168 INFO o.a.j.s.SaveService: Loading file: src/main/resources/JMeter.jmx +2017-12-13 04:50:17,340 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/html is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser +2017-12-13 04:50:17,351 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for application/xhtml+xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser +2017-12-13 04:50:17,352 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for application/xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser +2017-12-13 04:50:17,352 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser +2017-12-13 04:50:17,353 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/vnd.wap.wml is org.apache.jmeter.protocol.http.parser.RegexpHTMLParser +2017-12-13 04:50:17,353 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/css is org.apache.jmeter.protocol.http.parser.CssParser +2017-12-13 04:50:17,552 INFO o.a.j.JMeter: Creating summariser +2017-12-13 04:50:17,580 INFO o.a.j.e.StandardJMeterEngine: Running the test! +2017-12-13 04:50:17,581 INFO o.a.j.s.SampleEvent: List of sample_variables: [] +2017-12-13 04:50:17,582 INFO o.a.j.s.SampleEvent: List of sample_variables: [] +2017-12-13 04:50:17,590 INFO o.a.j.e.u.CompoundVariable: Note: Function class names must contain the string: '.functions.' +2017-12-13 04:50:17,590 INFO o.a.j.e.u.CompoundVariable: Note: Function class names must not contain the string: '.gui.' +2017-12-13 04:50:18,640 INFO o.a.j.JMeter: Running test (1513137018640) +2017-12-13 04:50:18,728 INFO o.a.j.e.StandardJMeterEngine: Starting ThreadGroup: 1 : Thread Group +2017-12-13 04:50:18,737 INFO o.a.j.e.StandardJMeterEngine: Starting 5 threads for group Thread Group. +2017-12-13 04:50:18,737 INFO o.a.j.e.StandardJMeterEngine: Thread will continue on error +2017-12-13 04:50:18,738 INFO o.a.j.t.ThreadGroup: Starting thread group... number=1 threads=5 ramp-up=1 perThread=200.0 delayedStart=false +2017-12-13 04:50:18,751 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-1 +2017-12-13 04:50:18,753 INFO o.a.j.t.ThreadGroup: Started thread group number 1 +2017-12-13 04:50:18,753 INFO o.a.j.e.StandardJMeterEngine: All thread groups have been started +2017-12-13 04:50:18,786 INFO o.a.j.p.h.s.HTTPHCAbstractImpl: Local host = MBP +2017-12-13 04:50:18,797 INFO o.a.j.p.h.s.HTTPHC4Impl: HTTP request retry count = 0 +2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: Note: Sample TimeStamps are START times +2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.default.encoding is set to ISO-8859-1 +2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.useNanoTime=true +2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.nanoThreadSleep=5000 +2017-12-13 04:50:18,954 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-2 +2017-12-13 04:50:19,152 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-3 +2017-12-13 04:50:19,257 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-3 +2017-12-13 04:50:19,257 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-3 +2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-2 +2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-1 +2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-2 +2017-12-13 04:50:19,265 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-1 +2017-12-13 04:50:19,353 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-4 +2017-12-13 04:50:19,365 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-4 +2017-12-13 04:50:19,365 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-4 +2017-12-13 04:50:19,557 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-5 +2017-12-13 04:50:19,573 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-5 +2017-12-13 04:50:19,573 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-5 +2017-12-13 04:50:19,573 INFO o.a.j.e.StandardJMeterEngine: Notifying test listeners of end of test +2017-12-13 04:50:19,575 INFO o.a.j.r.Summariser: summary = 5 in 00:00:01 = 5.4/s Avg: 155 Min: 10 Max: 388 Err: 4 (80.00%) diff --git a/jmeter/src/main/resources/20171205-JMeter-Jenkins.csv b/jmeter/src/main/resources/20171205-JMeter-Jenkins.csv deleted file mode 100644 index 719fc18f41..0000000000 --- a/jmeter/src/main/resources/20171205-JMeter-Jenkins.csv +++ /dev/null @@ -1,6 +0,0 @@ -timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect -1512454361862,181,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 181 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,181 -1512454361926,116,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 116 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,116 -1512454361862,181,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 181 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,3,3,0,0,181 -1512454362126,2,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,,2058,0,1,1,0,0,2 -1512454362326,2,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,,2058,0,1,1,0,0,2 diff --git a/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv b/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv deleted file mode 100644 index 92650ea36f..0000000000 --- a/jmeter/src/main/resources/20171213-JMeter-Jenkins.csv +++ /dev/null @@ -1,6 +0,0 @@ -timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect -1513133869106,1150,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 1,150 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1150 -1513133869106,1152,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,"The operation lasted too long: It took 1,152 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1152 -1513133869106,1150,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,"The operation lasted too long: It took 1,150 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1150 -1513133869106,1152,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 1,152 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1152 -1513133869104,1153,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 1,153 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1153 diff --git a/jmeter/src/main/resources/20171213-JMeter.csv b/jmeter/src/main/resources/20171213-JMeter.csv new file mode 100644 index 0000000000..6eb1a37cb0 --- /dev/null +++ b/jmeter/src/main/resources/20171213-JMeter.csv @@ -0,0 +1,6 @@ +timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect +1513134869133,1075,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,"The operation lasted too long: It took 1,075 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1075 +1513134869272,935,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 935 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,935 +1513134869133,1075,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 1,075 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1075 +1513134869272,935,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 935 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,934 +1513134869133,1074,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,"The operation lasted too long: It took 1,074 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1074 diff --git a/jmeter/src/main/resources/JMeter-Jenkins.jmx b/jmeter/src/main/resources/JMeter.jmx similarity index 99% rename from jmeter/src/main/resources/JMeter-Jenkins.jmx rename to jmeter/src/main/resources/JMeter.jmx index 49ce2dec1d..77bccb2b24 100644 --- a/jmeter/src/main/resources/JMeter-Jenkins.jmx +++ b/jmeter/src/main/resources/JMeter.jmx @@ -1,7 +1,7 @@ - + false false diff --git a/jmeter/src/main/resources/JMeter.jtl b/jmeter/src/main/resources/JMeter.jtl new file mode 100644 index 0000000000..f9259ef739 --- /dev/null +++ b/jmeter/src/main/resources/JMeter.jtl @@ -0,0 +1,43 @@ + + + + + Duration Assertion + true + false + The operation lasted too long: It took 83 milliseconds, but should not have lasted longer than 10 milliseconds. + + + + + Duration Assertion + true + false + The operation lasted too long: It took 388 milliseconds, but should not have lasted longer than 10 milliseconds. + + + + + Duration Assertion + true + false + The operation lasted too long: It took 281 milliseconds, but should not have lasted longer than 10 milliseconds. + + + + + Duration Assertion + false + false + + + + + Duration Assertion + true + false + The operation lasted too long: It took 13 milliseconds, but should not have lasted longer than 10 milliseconds. + + + + From c194284dddd5f79bd444b03e986a43aabe6d93f1 Mon Sep 17 00:00:00 2001 From: Dassi Orleando Date: Wed, 13 Dec 2017 04:59:11 +0100 Subject: [PATCH 30/36] Update spring jenkins module --- spring-jenkins-pipeline/scripted-pipeline-unix-nonunix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix index 861c38c8a2..6b775b6e56 100644 --- a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix +++ b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix @@ -75,13 +75,8 @@ node { withEnv(['JENKINS_NODE_COOKIE=dontkill']) { if (isUnix()) { sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &' - sh "while ! httping -qc1 http://localhost:8989 ; do sleep 1 ; done" - sh "curl http://localhost:8989" } else { bat 'start ./mvnw.cmd spring-boot:run -Dserver.port=8989' - // Here we need to check(loop) if localhost:8989 is up - // Once it's we continue de script - bat "curl.exe http://localhost:8989" } } } From 18c8747c98d0c89c64e1a7db8df80413737a4ef7 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 14 Dec 2017 06:26:03 +0200 Subject: [PATCH 31/36] BAEL-1248 google sheets api example (#3189) * google sheets api example * add dependencies * rename test * update test * add comment * trigger build * trigger build * Formatting to standards * Getting rid of stray tabs * Applying formatting rules to source files as well * trigger build --- libraries/pom.xml | 25 +++- .../google/sheets/GoogleAuthorizeUtil.java | 42 ++++++ .../google/sheets/SheetsServiceUtil.java | 23 +++ .../google-sheets-client-secret.json | 1 + .../sheets/GoogleSheetsIntegrationTest.java | 140 ++++++++++++++++++ 5 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 libraries/src/main/java/com/baeldung/google/sheets/GoogleAuthorizeUtil.java create mode 100644 libraries/src/main/java/com/baeldung/google/sheets/SheetsServiceUtil.java create mode 100644 libraries/src/main/resources/google-sheets-client-secret.json create mode 100644 libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java diff --git a/libraries/pom.xml b/libraries/pom.xml index eaa2d9d38f..3627e74472 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -633,9 +633,26 @@ ${googleclient.version} - com.google.http-client - google-http-client-gson - ${googleclient.version} + com.google.http-client + google-http-client-gson + ${googleclient.version} + + + + + com.google.api-client + google-api-client + ${google-api.version} + + + com.google.oauth-client + google-oauth-client-jetty + ${google-api.version} + + + com.google.apis + google-api-services-sheets + ${google-sheets.version} @@ -710,5 +727,7 @@ 1.0.0 3.8.4 2.5.5 + 1.23.0 + v4-rev493-1.21.0 \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/google/sheets/GoogleAuthorizeUtil.java b/libraries/src/main/java/com/baeldung/google/sheets/GoogleAuthorizeUtil.java new file mode 100644 index 0000000000..650a1d084c --- /dev/null +++ b/libraries/src/main/java/com/baeldung/google/sheets/GoogleAuthorizeUtil.java @@ -0,0 +1,42 @@ +package com.baeldung.google.sheets; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.GeneralSecurityException; +import java.util.Arrays; +import java.util.List; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; +import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; +import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; +import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.util.store.MemoryDataStoreFactory; +import com.google.api.services.sheets.v4.SheetsScopes; + +public class GoogleAuthorizeUtil { + public static Credential authorize() throws IOException, GeneralSecurityException { + InputStream in = GoogleAuthorizeUtil.class.getResourceAsStream("/google-sheets-client-secret.json"); + GoogleClientSecrets clientSecrets = GoogleClientSecrets + .load(JacksonFactory.getDefaultInstance(), new InputStreamReader(in)); + + List scopes = Arrays.asList(SheetsScopes.SPREADSHEETS); + + GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow + .Builder(GoogleNetHttpTransport.newTrustedTransport(), + JacksonFactory.getDefaultInstance(), + clientSecrets, + scopes) + .setDataStoreFactory(new MemoryDataStoreFactory()) + .setAccessType("offline") + .build(); + Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()) + .authorize("user"); + + return credential; + } + +} diff --git a/libraries/src/main/java/com/baeldung/google/sheets/SheetsServiceUtil.java b/libraries/src/main/java/com/baeldung/google/sheets/SheetsServiceUtil.java new file mode 100644 index 0000000000..bbce96f389 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/google/sheets/SheetsServiceUtil.java @@ -0,0 +1,23 @@ +package com.baeldung.google.sheets; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.sheets.v4.Sheets; + +public class SheetsServiceUtil { + + private static final String APPLICATION_NAME = "Google Sheets Example"; + + public static Sheets getSheetsService() throws IOException, GeneralSecurityException { + Credential credential = GoogleAuthorizeUtil.authorize(); + return new Sheets.Builder(GoogleNetHttpTransport.newTrustedTransport(), + JacksonFactory.getDefaultInstance(), credential) + .setApplicationName(APPLICATION_NAME) + .build(); + } + +} diff --git a/libraries/src/main/resources/google-sheets-client-secret.json b/libraries/src/main/resources/google-sheets-client-secret.json new file mode 100644 index 0000000000..c92ccd6b9b --- /dev/null +++ b/libraries/src/main/resources/google-sheets-client-secret.json @@ -0,0 +1 @@ +{"installed":{"client_id":"394827218507-2ev02b2ha8plt7g2lh5nqse02ee737cf.apps.googleusercontent.com","project_id":"decisive-octane-187810","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"2MnN1DfenoCGWMay3v8Bf7eI","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java new file mode 100644 index 0000000000..5280073be2 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java @@ -0,0 +1,140 @@ +package com.baeldung.google.sheets; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.api.services.sheets.v4.Sheets; +import com.google.api.services.sheets.v4.model.AppendValuesResponse; +import com.google.api.services.sheets.v4.model.BatchGetValuesResponse; +import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest; +import com.google.api.services.sheets.v4.model.BatchUpdateValuesRequest; +import com.google.api.services.sheets.v4.model.BatchUpdateValuesResponse; +import com.google.api.services.sheets.v4.model.CopyPasteRequest; +import com.google.api.services.sheets.v4.model.GridRange; +import com.google.api.services.sheets.v4.model.Request; +import com.google.api.services.sheets.v4.model.Spreadsheet; +import com.google.api.services.sheets.v4.model.SpreadsheetProperties; +import com.google.api.services.sheets.v4.model.UpdateSpreadsheetPropertiesRequest; +import com.google.api.services.sheets.v4.model.UpdateValuesResponse; +import com.google.api.services.sheets.v4.model.ValueRange; + +import static org.assertj.core.api.Assertions.*; + +public class GoogleSheetsIntegrationTest { + + private static Sheets sheetsService; + + // this id can be replaced with your spreadsheet id + // otherwise be advised that multiple people may run this test and update the public spreadsheet + private static final String SPREADSHEET_ID = "1sILuxZUnyl_7-MlNThjt765oWshN3Xs-PPLfqYe4DhI"; + + @BeforeClass + public static void setup() throws GeneralSecurityException, IOException { + sheetsService = SheetsServiceUtil.getSheetsService(); + } + + @Test + public void whenWriteSheet_thenReadSheetOk() throws IOException { + ValueRange body = new ValueRange() + .setValues(Arrays.asList( + Arrays.asList("Expenses January"), + Arrays.asList("books", "30"), + Arrays.asList("pens", "10"), + Arrays.asList("Expenses February"), + Arrays.asList("clothes", "20"), + Arrays.asList("shoes", "5"))); + UpdateValuesResponse result = sheetsService.spreadsheets().values() + .update(SPREADSHEET_ID, "A1", body) + .setValueInputOption("RAW") + .execute(); + + List data = new ArrayList<>(); + data.add(new ValueRange() + .setRange("D1") + .setValues(Arrays.asList( + Arrays.asList("January Total", "=B2+B3")))); + data.add(new ValueRange() + .setRange("D4") + .setValues(Arrays.asList( + Arrays.asList("February Total", "=B5+B6")))); + + BatchUpdateValuesRequest batchBody = new BatchUpdateValuesRequest() + .setValueInputOption("USER_ENTERED") + .setData(data); + BatchUpdateValuesResponse batchResult = + sheetsService.spreadsheets().values() + .batchUpdate(SPREADSHEET_ID, batchBody) + .execute(); + + List ranges = Arrays.asList("E1","E4"); + BatchGetValuesResponse readResult = + sheetsService.spreadsheets().values() + .batchGet(SPREADSHEET_ID) + .setRanges(ranges) + .execute(); + + ValueRange januaryTotal = readResult.getValueRanges().get(0); + assertThat(januaryTotal.getValues().get(0).get(0)).isEqualTo("40"); + + ValueRange febTotal = readResult.getValueRanges().get(1); + assertThat(febTotal.getValues().get(0).get(0)).isEqualTo("25"); + + ValueRange appendBody = new ValueRange() + .setValues(Arrays.asList( + Arrays.asList("Total", "=E1+E4"))); + AppendValuesResponse appendResult = + sheetsService.spreadsheets().values() + .append(SPREADSHEET_ID, "A1", appendBody) + .setValueInputOption("USER_ENTERED") + .setInsertDataOption("INSERT_ROWS") + .setIncludeValuesInResponse(true) + .execute(); + + ValueRange total = appendResult.getUpdates().getUpdatedData(); + assertThat(total.getValues().get(0).get(1)).isEqualTo("65"); + } + + + @Test + public void whenUpdateSpreadSheetTitle_thenOk() throws IOException { + + UpdateSpreadsheetPropertiesRequest updateRequest = new UpdateSpreadsheetPropertiesRequest() + .setFields("*") + .setProperties(new SpreadsheetProperties().setTitle("Expenses")); + + CopyPasteRequest copyRequest = new CopyPasteRequest() + .setSource(new GridRange().setSheetId(0) + .setStartColumnIndex(0).setEndColumnIndex(2) + .setStartRowIndex(0).setEndRowIndex(1)) + .setDestination(new GridRange().setSheetId(1) + .setStartColumnIndex(0).setEndColumnIndex(2) + .setStartRowIndex(0).setEndRowIndex(1)) + .setPasteType("PASTE_VALUES"); + + List requests = new ArrayList<>(); + + requests.add(new Request().setCopyPaste(copyRequest)); + requests.add(new Request().setUpdateSpreadsheetProperties(updateRequest)); + + BatchUpdateSpreadsheetRequest body = + new BatchUpdateSpreadsheetRequest().setRequests(requests); + + sheetsService.spreadsheets().batchUpdate(SPREADSHEET_ID, body).execute(); + } + + @Test + public void whenCreateSpreadSheet_thenIdOk() throws IOException { + Spreadsheet spreadSheet = new Spreadsheet() + .setProperties(new SpreadsheetProperties().setTitle("My Spreadsheet")); + Spreadsheet result = sheetsService.spreadsheets().create(spreadSheet).execute(); + + assertThat(result.getSpreadsheetId()).isNotNull(); + } + +} From 04df1cfef043caec5f64a9aa4ed5e7737da74fae Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Thu, 14 Dec 2017 17:06:17 +0100 Subject: [PATCH 32/36] Remove spring-flyway (#3240) * Remove spring-flyway * Remove spring-flyway --- ... WaitingForThreadsToFinishManualTest.java} | 66 +------------------ flyway/pom.xml | 52 --------------- flyway/spring-flyway/.gitignore | 24 ------- flyway/spring-flyway/pom.xml | 57 ---------------- .../springflyway/SpringFlywayApplication.java | 12 ---- .../springflyway/entities/Customer.java | 28 -------- .../migration/V2__uk_lastname_customer.java | 14 ---- .../repositories/CustomerRepository.java | 11 ---- ...sitoryInitialMigrationIntegrationTest.java | 28 -------- ...erRepositoryInsertDataIntegrationTest.java | 35 ---------- ...ullConstraintMigrationIntegrationTest.java | 25 ------- ...onstraintJavaMigrationIntegrationTest.java | 29 -------- ...queConstraintMigrationIntegrationTest.java | 27 -------- .../src/test/resources/application.properties | 1 - .../migration/V1_0__create_table_customer.sql | 6 -- .../db/migration/V1_1__insert_customer.sql | 6 -- .../migration/V1_2__make_email_not_null.sql | 1 - .../db/migration/V1_3__make_email_unique.sql | 1 - pom.xml | 1 - 19 files changed, 2 insertions(+), 422 deletions(-) rename core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/{WaitingForThreadsToFinishTest.java => WaitingForThreadsToFinishManualTest.java} (72%) delete mode 100644 flyway/pom.xml delete mode 100644 flyway/spring-flyway/.gitignore delete mode 100644 flyway/spring-flyway/pom.xml delete mode 100644 flyway/spring-flyway/src/main/java/com/baeldung/springflyway/SpringFlywayApplication.java delete mode 100644 flyway/spring-flyway/src/main/java/com/baeldung/springflyway/entities/Customer.java delete mode 100644 flyway/spring-flyway/src/main/java/com/baeldung/springflyway/migration/V2__uk_lastname_customer.java delete mode 100644 flyway/spring-flyway/src/main/java/com/baeldung/springflyway/repositories/CustomerRepository.java delete mode 100644 flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInitialMigrationIntegrationTest.java delete mode 100644 flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInsertDataIntegrationTest.java delete mode 100644 flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryNotNullConstraintMigrationIntegrationTest.java delete mode 100644 flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintJavaMigrationIntegrationTest.java delete mode 100644 flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintMigrationIntegrationTest.java delete mode 100644 flyway/spring-flyway/src/test/resources/application.properties delete mode 100644 flyway/spring-flyway/src/test/resources/db/migration/V1_0__create_table_customer.sql delete mode 100644 flyway/spring-flyway/src/test/resources/db/migration/V1_1__insert_customer.sql delete mode 100644 flyway/spring-flyway/src/test/resources/db/migration/V1_2__make_email_not_null.sql delete mode 100644 flyway/spring-flyway/src/test/resources/db/migration/V1_3__make_email_unique.sql diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java similarity index 72% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java rename to core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java index 7e2bf590fd..cd8b015be2 100644 --- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java +++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java @@ -10,9 +10,9 @@ import java.util.concurrent.*; import static junit.framework.TestCase.assertTrue; -public class WaitingForThreadsToFinishTest { +public class WaitingForThreadsToFinishManualTest { - private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishTest.class); + private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishManualTest.class); private final static ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10); public void awaitTerminationAfterShutdown(ExecutorService threadPool) { @@ -142,66 +142,4 @@ public class WaitingForThreadsToFinishTest { awaitTerminationAfterShutdown(WORKER_THREAD_POOL); } } - - @Test - public void givenMultipleThreads_whenUsingCompletableFutures_thenMainThreadShouldWaitForAllToFinish() { - - CompletableFuture future1 = CompletableFuture.supplyAsync(() -> { - - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return "Hello"; - }); - - CompletableFuture future2 = CompletableFuture.supplyAsync(() -> { - - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return "Beautiful"; - }); - - CompletableFuture future3 = CompletableFuture.supplyAsync(() -> { - - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return "World"; - }); - - long startProcessingTime = System.currentTimeMillis(); - CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3); - combinedFuture.join(); - - long totalProcessingTime = System.currentTimeMillis() - startProcessingTime; - assertTrue(totalProcessingTime >= 5000 && totalProcessingTime < 6000); - - LOG.debug("Responses from all threads are available after " + totalProcessingTime + " milliseconds"); - - try { - String thread1Response = future1.get(); - assertTrue(thread1Response.equals("Hello")); - - String thread2Response = future2.get(); - assertTrue(thread2Response.equals("Beautiful")); - - String thread3Response = future3.get(); - assertTrue(thread3Response.equals("World")); - - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - - awaitTerminationAfterShutdown(WORKER_THREAD_POOL); - } } diff --git a/flyway/pom.xml b/flyway/pom.xml deleted file mode 100644 index 5cb8fabe67..0000000000 --- a/flyway/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - 4.0.0 - flyway - 1.0 - flyway - pom - A sample project to demonstrate Flyway migrations - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - spring-flyway - - - - - mysql - mysql-connector-java - ${mysql.version} - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - - - - org.flywaydb - flyway-maven-plugin - ${flyway-maven-plugin.version} - - - - - 6.0.5 - 4.0.3 - 1.5.8.RELEASE - - \ No newline at end of file diff --git a/flyway/spring-flyway/.gitignore b/flyway/spring-flyway/.gitignore deleted file mode 100644 index 2af7cefb0a..0000000000 --- a/flyway/spring-flyway/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ \ No newline at end of file diff --git a/flyway/spring-flyway/pom.xml b/flyway/spring-flyway/pom.xml deleted file mode 100644 index cf5703cfab..0000000000 --- a/flyway/spring-flyway/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - - spring-flyway - 0.0.1-SNAPSHOT - jar - - spring-flyway - Spring Boot Test Flyway Migrations - - - flyway - com.baeldung - 1.0 - ../../flyway - - - - UTF-8 - UTF-8 - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.flywaydb - flyway-core - - - org.projectlombok - lombok - - - com.h2database - h2 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/SpringFlywayApplication.java b/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/SpringFlywayApplication.java deleted file mode 100644 index 9218fbc88d..0000000000 --- a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/SpringFlywayApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.springflyway; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringFlywayApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringFlywayApplication.class, args); - } -} diff --git a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/entities/Customer.java b/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/entities/Customer.java deleted file mode 100644 index 194b961d2d..0000000000 --- a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/entities/Customer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.springflyway.entities; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - -@Entity -@Data -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class Customer { - - @Id - @GeneratedValue - private Long id; - - private String firstName; - private String lastName; - - private String email; - -} diff --git a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/migration/V2__uk_lastname_customer.java b/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/migration/V2__uk_lastname_customer.java deleted file mode 100644 index 52b851546b..0000000000 --- a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/migration/V2__uk_lastname_customer.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.springflyway.migration; - -import org.flywaydb.core.api.migration.spring.SpringJdbcMigration; -import org.springframework.jdbc.core.JdbcTemplate; - -public class V2__uk_lastname_customer implements SpringJdbcMigration { - - final String CUSTOMER_LASTNAME_UK = "ALTER TABLE customer ADD CONSTRAINT uk_customer_lastname UNIQUE(last_name);"; - - @Override - public void migrate(final JdbcTemplate jdbcTemplate) throws Exception { - jdbcTemplate.execute(CUSTOMER_LASTNAME_UK); - } -} diff --git a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/repositories/CustomerRepository.java b/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/repositories/CustomerRepository.java deleted file mode 100644 index 0a1fb5a146..0000000000 --- a/flyway/spring-flyway/src/main/java/com/baeldung/springflyway/repositories/CustomerRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.springflyway.repositories; - -import com.baeldung.springflyway.entities.Customer; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface CustomerRepository extends JpaRepository { - - Optional findByEmail(String email); -} diff --git a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInitialMigrationIntegrationTest.java b/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInitialMigrationIntegrationTest.java deleted file mode 100644 index 59ef5820d7..0000000000 --- a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInitialMigrationIntegrationTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.springflyway; - -import com.baeldung.springflyway.entities.Customer; -import com.baeldung.springflyway.repositories.CustomerRepository; -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 static org.junit.Assert.assertNotNull; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CustomerRepositoryInitialMigrationIntegrationTest { - - @Autowired CustomerRepository customerRepository; - - @Test - public void givenSchemaCreationMigration_whenTryingToCreateACustomer_thenSuccess() { - Customer customer = customerRepository.save(Customer - .builder() - .email("customer@email.com") - .build()); - assertNotNull(customer.getId()); - } - -} diff --git a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInsertDataIntegrationTest.java b/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInsertDataIntegrationTest.java deleted file mode 100644 index 3feedf2fd9..0000000000 --- a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryInsertDataIntegrationTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.springflyway; - -import com.baeldung.springflyway.entities.Customer; -import com.baeldung.springflyway.repositories.CustomerRepository; -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 java.util.List; -import java.util.Optional; - -import static org.junit.Assert.*; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CustomerRepositoryInsertDataIntegrationTest { - - @Autowired CustomerRepository customerRepository; - - @Test - public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASpecificCustomerIsFound() { - Optional customerOptional = customerRepository.findByEmail("email@email.com"); - assertTrue(customerOptional.isPresent()); - } - - @Test - public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASetOfCustomersIsFound() { - List customers = customerRepository.findAll(); - assertNotNull(customers); - assertEquals(customers.size(), 6); - } - -} diff --git a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryNotNullConstraintMigrationIntegrationTest.java b/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryNotNullConstraintMigrationIntegrationTest.java deleted file mode 100644 index 9ec5d4d77e..0000000000 --- a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryNotNullConstraintMigrationIntegrationTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.springflyway; - -import com.baeldung.springflyway.entities.Customer; -import com.baeldung.springflyway.repositories.CustomerRepository; -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.dao.DataIntegrityViolationException; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CustomerRepositoryNotNullConstraintMigrationIntegrationTest { - - @Autowired CustomerRepository customerRepository; - - @Test(expected = DataIntegrityViolationException.class) - public void givenTheNotNullConstraintMigrations_whenInsertingACustomerWithNullEmail_thenThrowException() { - customerRepository.save(Customer - .builder() - .build()); - } - -} diff --git a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintJavaMigrationIntegrationTest.java b/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintJavaMigrationIntegrationTest.java deleted file mode 100644 index f615f477bc..0000000000 --- a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintJavaMigrationIntegrationTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.springflyway; - -import com.baeldung.springflyway.entities.Customer; -import com.baeldung.springflyway.repositories.CustomerRepository; -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.dao.DataIntegrityViolationException; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(properties = { - "flyway.locations[0]=db/migration", "flyway.locations[1]=com/baeldung/springflyway/migration" -}) -public class CustomerRepositoryUniqueConstraintJavaMigrationIntegrationTest { - - @Autowired CustomerRepository customerRepository; - - @Test(expected = DataIntegrityViolationException.class) - public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingLastNameCustomer_thenThrowException() { - customerRepository.save(Customer - .builder() - .lastName("LastName") - .build()); - - } - -} diff --git a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintMigrationIntegrationTest.java b/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintMigrationIntegrationTest.java deleted file mode 100644 index e9ac34b384..0000000000 --- a/flyway/spring-flyway/src/test/java/com/baeldung/springflyway/CustomerRepositoryUniqueConstraintMigrationIntegrationTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.springflyway; - -import com.baeldung.springflyway.entities.Customer; -import com.baeldung.springflyway.repositories.CustomerRepository; -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.dao.DataIntegrityViolationException; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CustomerRepositoryUniqueConstraintMigrationIntegrationTest { - - @Autowired CustomerRepository customerRepository; - - @Test(expected = DataIntegrityViolationException.class) - public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingEmailCustomer_thenThrowException() { - customerRepository.save(Customer - .builder() - .email("email@email.com") - .build()); - - } - -} diff --git a/flyway/spring-flyway/src/test/resources/application.properties b/flyway/spring-flyway/src/test/resources/application.properties deleted file mode 100644 index 5656ca79ce..0000000000 --- a/flyway/spring-flyway/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.jpa.hibernate.ddl-auto=validate \ No newline at end of file diff --git a/flyway/spring-flyway/src/test/resources/db/migration/V1_0__create_table_customer.sql b/flyway/spring-flyway/src/test/resources/db/migration/V1_0__create_table_customer.sql deleted file mode 100644 index 8c65253ed8..0000000000 --- a/flyway/spring-flyway/src/test/resources/db/migration/V1_0__create_table_customer.sql +++ /dev/null @@ -1,6 +0,0 @@ -create table if not exists customer ( - id bigint AUTO_INCREMENT not null primary key, - first_name varchar(255) , - last_name varchar(255) , - email varchar(255) -); \ No newline at end of file diff --git a/flyway/spring-flyway/src/test/resources/db/migration/V1_1__insert_customer.sql b/flyway/spring-flyway/src/test/resources/db/migration/V1_1__insert_customer.sql deleted file mode 100644 index 6bba6e00a1..0000000000 --- a/flyway/spring-flyway/src/test/resources/db/migration/V1_1__insert_customer.sql +++ /dev/null @@ -1,6 +0,0 @@ -insert into customer (first_name, last_name, email) values ('FirstName', 'LastName', 'email@email.com'); -insert into customer (first_name, last_name, email) values ('FirstName1', 'LastName1', 'email1@email.com'); -insert into customer (first_name, last_name, email) values ('FirstName2', 'LastName2', 'email2@email.com'); -insert into customer (first_name, last_name, email) values ('FirstName3', 'LastName3', 'email3@email.com'); -insert into customer (first_name, last_name, email) values ('FirstName4', 'LastName4', 'email4@email.com'); -insert into customer (first_name, last_name, email) values ('FirstName5', 'LastName5', 'email5@email.com'); \ No newline at end of file diff --git a/flyway/spring-flyway/src/test/resources/db/migration/V1_2__make_email_not_null.sql b/flyway/spring-flyway/src/test/resources/db/migration/V1_2__make_email_not_null.sql deleted file mode 100644 index b1cc396741..0000000000 --- a/flyway/spring-flyway/src/test/resources/db/migration/V1_2__make_email_not_null.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE customer ALTER email SET NOT NULL; \ No newline at end of file diff --git a/flyway/spring-flyway/src/test/resources/db/migration/V1_3__make_email_unique.sql b/flyway/spring-flyway/src/test/resources/db/migration/V1_3__make_email_unique.sql deleted file mode 100644 index 19d738fe46..0000000000 --- a/flyway/spring-flyway/src/test/resources/db/migration/V1_3__make_email_unique.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE customer ADD CONSTRAINT uk_customer_email UNIQUE(email); \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2c611e6efe..fa5eb83b0c 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,6 @@ feign - flyway From 9627971b46c2257a0213685108d0b250b1d00038 Mon Sep 17 00:00:00 2001 From: Muhammed Almas Date: Thu, 14 Dec 2017 22:24:27 +0530 Subject: [PATCH 33/36] BAEL-1375 Using compute for every usage. (#3242) --- .../java/com/baeldung/counter/CounterUtil.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java b/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java index 647fbfb0cc..afd7202892 100644 --- a/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java +++ b/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java @@ -38,23 +38,14 @@ public class CounterUtil { public static void counterWithMutableInteger(Map counterMap) { for (String country : COUNTRY_NAMES) { - MutableInteger oldValue = counterMap.get(country); - if (oldValue != null) { - oldValue.increment(); - } else { - counterMap.put(country, new MutableInteger(1)); - } + counterMap.compute(country, (k, v) -> v == null ? new MutableInteger(0) : v) + .increment(); } } public static void counterWithPrimitiveArray(Map counterMap) { for (String country : COUNTRY_NAMES) { - int[] oldCounter = counterMap.get(country); - if (oldCounter != null) { - oldCounter[0] += 1; - } else { - counterMap.put(country, new int[] { 1 }); - } + counterMap.compute(country, (k, v) -> v == null ? new int[] { 0 } : v)[0]++; } } From 92c92ee96c49b97abbdc04e60fcef72f3b7afbcc Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 14 Dec 2017 22:24:31 +0200 Subject: [PATCH 34/36] fix windows jenkins script --- .../scripted-pipeline-unix-nonunix | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix index 6b775b6e56..e9cae64d3d 100644 --- a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix +++ b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix @@ -14,8 +14,10 @@ node { stage("Checkstyle") { if (isUnix()) { sh "./mvnw checkstyle:checkstyle" - - step([$class: 'CheckStylePublisher', + } else { + bat "./mvnw.cmd checkstyle:checkstyle" + } + step([$class: 'CheckStylePublisher', canRunOnFailed: true, defaultEncoding: '', healthy: '100', @@ -23,18 +25,6 @@ node { unHealthy: '90', useStableBuildAsReference: true ]) - } else { - bat "./mvnw.cmd checkstyle:checkstyle" - - step([$class: 'CheckStylePublisher', - canRunOnFailed: true, - defaultEncoding: '', - healthy: '100', - pattern: '**\target\checkstyle-result.xml', - unHealthy: '90', - useStableBuildAsReference: true - ]) - } } } } @@ -44,32 +34,27 @@ node { stage("Runing unit tests") { if (isUnix()) { sh "./mvnw test -Punit" - - step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) } else { bat "./mvnw.cmd test -Punit" - - step([$class: 'JUnitResultArchiver', testResults: '**\target\surefire-reports\TEST-*UnitTest.xml']) } + step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) + } }, 'Integration tests': { stage("Runing integration tests") { if (isUnix()) { sh "./mvnw test -Pintegration" - - step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*IntegrationTest.xml']) } else { bat "./mvnw.cmd test -Pintegration" - - step([$class: 'JUnitResultArchiver', testResults: '**\target\surefire-reports\TEST-*IntegrationTest.xml']) } + step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*IntegrationTest.xml']) } }, 'Deployment': { stage("Staging") { if (isUnix()) { sh "pid=\$(lsof -i:8989 -t); kill -TERM \$pid || kill -KILL \$pid" } else { - bat "FOR /F 'tokens=5 delims= ' %%P IN ('netstat -ano ^| findstr :8989') DO TaskKill.exe /PID %%P" + bat "FOR /F \"tokens=5 delims= \" %%G IN (\"netstat -a | findstr :8989\") DO TaskKill.exe /PID %%G /fi \"memusage gt 0\"" } withEnv(['JENKINS_NODE_COOKIE=dontkill']) { From 171d28a9d17c8bbb5576b78fe13773624a3e1aad Mon Sep 17 00:00:00 2001 From: ocheja Date: Fri, 15 Dec 2017 07:06:41 +0900 Subject: [PATCH 35/36] Remove verbose file info content (#3238) * Define beans for handling different message types in a lean chat app * Add class based spring beans configuration * Define spring configuration in XML for constructor based bean injection * Refactor package structure to separate constructor based bean injection code set from setter based bean injection code set * Define configuration and classes specific to setter-based bean injection. * Implement tests for constructor-based and setter-based bean injections * develop codes for explaining type erasure * Write unit tests for type erasure examples * Remove evaluation article code * Modify type erasure examples and unit tests * Modify type erasure examples and unit tests * Add expected exception in TypeErasureUnitTest * Correct grammar in class name * Implement File Manager app to demonstrate Polymorphism. Develop unit tests for Polymorphism article code * Add examples for static polymorphism * Change sysout statments to slf4j log info statements * Add assertions and expected errors check on Test * Add assertions and expected errors check on Test * Correct compile time error of symbol not found * Removed commented out non-compiling test. * Replace string concatenations with String.format * Replace string concatenations with String.format * Remove verbose file info descriptor and replace with simpler one --- .../src/main/java/com/baeldung/polymorphism/GenericFile.java | 2 +- .../src/main/java/com/baeldung/polymorphism/ImageFile.java | 2 +- core-java/src/main/java/com/baeldung/polymorphism/TextFile.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java/src/main/java/com/baeldung/polymorphism/GenericFile.java b/core-java/src/main/java/com/baeldung/polymorphism/GenericFile.java index 03e704f36f..85acbc5be0 100644 --- a/core-java/src/main/java/com/baeldung/polymorphism/GenericFile.java +++ b/core-java/src/main/java/com/baeldung/polymorphism/GenericFile.java @@ -54,7 +54,7 @@ public class GenericFile { } public String getFileInfo() { - return String.format("File Name: %s\n" + " Extension: %s\n" + " Date Created: %s\n" + " Version: %s\n", this.getName(), this.getExtension(), this.getDateCreated(), this.getVersion()); + return "Generic File Impl"; } public Object read() { diff --git a/core-java/src/main/java/com/baeldung/polymorphism/ImageFile.java b/core-java/src/main/java/com/baeldung/polymorphism/ImageFile.java index e237f3f826..54eb24af5e 100644 --- a/core-java/src/main/java/com/baeldung/polymorphism/ImageFile.java +++ b/core-java/src/main/java/com/baeldung/polymorphism/ImageFile.java @@ -30,7 +30,7 @@ public class ImageFile extends GenericFile { } public String getFileInfo() { - return String.format(" %s Height: %d\n Width: %d", super.getFileInfo(), this.getHeight(), this.getWidth()); + return "Image File Impl"; } public String read() { diff --git a/core-java/src/main/java/com/baeldung/polymorphism/TextFile.java b/core-java/src/main/java/com/baeldung/polymorphism/TextFile.java index 2c28c968b8..0103291c5a 100644 --- a/core-java/src/main/java/com/baeldung/polymorphism/TextFile.java +++ b/core-java/src/main/java/com/baeldung/polymorphism/TextFile.java @@ -21,7 +21,7 @@ public class TextFile extends GenericFile { } public String getFileInfo() { - return String.format(" %s Word Count: %d", super.getFileInfo(), wordCount); + return "Text File Impl"; } public String read() { From ae109dfb7cf220cc1deffb010a226bf55acc81f7 Mon Sep 17 00:00:00 2001 From: Jose Bob Santos Jr Date: Fri, 15 Dec 2017 09:50:51 +0800 Subject: [PATCH 36/36] BAEL-1330 Primitive Type Streams in Java 8 (#3106) * initial commit for first article evaluation * fixed compilation error * removed final keywords for compliance * added unit tests and refactored as needed * refactored application-context.xml to use self-closing tags * renamed tests to use UnitTest suffix * removed unnecessary annotation * added code samples for primitive streams * removed sample code and tests for evaluation article * renamed unit test to proper unit test naming * added a test to show boxed method * added the assertion to the test fox boxed * changed mapToInt test to use Arrays.asList instead of a POJO as per Grzegorz and Eugen --- .../com/baeldung/stream/PrimitiveStreams.java | 23 +++++ .../stream/PrimitiveStreamsUnitTest.java | 97 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/stream/PrimitiveStreams.java create mode 100644 core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java diff --git a/core-java-8/src/main/java/com/baeldung/stream/PrimitiveStreams.java b/core-java-8/src/main/java/com/baeldung/stream/PrimitiveStreams.java new file mode 100644 index 0000000000..b0afb65a35 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/stream/PrimitiveStreams.java @@ -0,0 +1,23 @@ +package com.baeldung.stream; + +import java.util.Arrays; +import java.util.stream.IntStream; + +class PrimitiveStreams { + + int min(int[] integers) { + return Arrays.stream(integers).min().getAsInt(); + } + + int max(int... integers) { + return IntStream.of(integers).max().getAsInt(); + } + + int sum(int... integers) { + return IntStream.of(integers).sum(); + } + + double avg(int... integers) { + return IntStream.of(integers).average().getAsDouble(); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java b/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java new file mode 100644 index 0000000000..75078d75bc --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java @@ -0,0 +1,97 @@ +package com.baeldung.stream; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class PrimitiveStreamsUnitTest { + + private PrimitiveStreams streams = new PrimitiveStreams(); + + @Test + public void givenAnArrayOfIntegersWhenMinIsCalledThenCorrectMinIsReturned() { + int[] integers = new int[] {20, 98, 12, 7, 35}; + int min = streams.min(integers); // returns 7 + + assertEquals(7, min); + } + + @Test + public void givenAnArrayOfIntegersWhenMaxIsCalledThenCorrectMaxIsReturned() { + int max = streams.max(20, 98, 12, 7, 35); + + assertEquals(98, max); + } + + @Test + public void givenAnArrayOfIntegersWhenSumIsCalledThenCorrectSumIsReturned() { + int sum = streams.sum(20, 98, 12, 7, 35); + + assertEquals(172, sum); + } + + @Test + public void givenAnArrayOfIntegersWhenAvgIsCalledThenCorrectAvgIsReturned() { + double avg = streams.avg(20, 98, 12, 7, 35); + + assertTrue(34.4 == avg); + } + + @Test + public void givenARangeOfIntegersWhenIntStreamSumIsCalledThenCorrectSumIsReturned() { + int sum = IntStream.range(1, 10).sum(); + + assertEquals(45, sum); + } + + @Test + public void givenARangeClosedOfIntegersWhenIntStreamSumIsCalledThenCorrectSumIsReturned() { + int sum = IntStream.rangeClosed(1, 10).sum(); + + assertEquals(55, sum); + } + + @Test + public void givenARangeWhenForEachIsCalledThenTheIndicesWillBePrinted() { + IntStream.rangeClosed(1, 5).parallel().forEach(System.out::println); + } + + @Test + public void givenAnArrayWhenSumIsCalledThenTheCorrectSumIsReturned() { + + int sum = Arrays.asList(33,45).stream().mapToInt(a -> a).sum(); + + assertEquals(78, sum); + } + + @Test + public void givenAnIntStreamThenGetTheEvenIntegers() { + List evenInts = IntStream.rangeClosed(1, 10) + .filter(i -> i % 2 == 0) + .boxed() + .collect(Collectors.toList()); + + List expected = IntStream.of(2, 4, 6, 8, 10).boxed().collect(Collectors.toList()); + + assertEquals(expected, evenInts); + } + + class Person { + private int age; + + Person(int age) { + this.age = age; + } + + int getAge() { + return age; + } + } +} \ No newline at end of file