From 581a897577450ab7a3bc3c45ffe421bbe0e4f3b2 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Sun, 9 May 2021 23:49:27 +0200 Subject: [PATCH 001/114] BAEL-3682 remove empty test --- .../java/com/baeldung/SpringContextTest.java | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 spring-boot-rest/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-rest/src/test/java/com/baeldung/SpringContextTest.java b/spring-boot-rest/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index 9cba7f8fc1..0000000000 --- a/spring-boot-rest/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,16 +0,0 @@ -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(classes = {SpringBootRestApplication.class}) -public class SpringContextTest { - - @Test - public void contextLoads() { - } - -} From 525abe9831eff4fdc3cdd12fff2375ca17c29965 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Sun, 9 May 2021 23:49:51 +0200 Subject: [PATCH 002/114] BAEL-3682 reuse url --- .../test/java/com/baeldung/web/FooPageableLiveTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java index 6a365f3bd5..dc60c0e422 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java @@ -43,12 +43,12 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { public final String createAsUri() { return createAsUri(new Foo(randomAlphabetic(6))); } - + @Override @Test public void whenResourcesAreRetrievedPaged_then200IsReceived() { this.create(); - + final Response response = RestAssured.get(getPageableURL() + "?page=0&size=10"); assertThat(response.getStatusCode(), is(200)); @@ -74,7 +74,7 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { } protected String getPageableURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/foos/pageable"; + return getURL() + "/pageable"; } - + } From 099b9d514fc0bf09ffd04b5c9bfdc1341d6d5274 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Sun, 9 May 2021 23:51:40 +0200 Subject: [PATCH 003/114] BAEL-3682 isolate test by cleaning the foo records to fix bulk test run --- .../web/FooControllerAppIntegrationTest.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java index 3300b91fde..5e8a190fb0 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java @@ -1,5 +1,11 @@ package com.baeldung.web; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.baeldung.persistence.dao.IFooDao; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -8,12 +14,8 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; - /** - * + * * We'll start the whole context, but not the server. We'll mock the REST calls instead. * */ @@ -25,6 +27,14 @@ public class FooControllerAppIntegrationTest { @Autowired private MockMvc mockMvc; + @Autowired + private IFooDao fooDao; + + @Before + public void setup(){ + this.fooDao.deleteAll(); + } + @Test public void whenFindPaginatedRequest_thenEmptyResponse() throws Exception { this.mockMvc.perform(get("/foos").param("page", "0") From e5c3f48f866cf792cadf4c5a4cce3cb909707e63 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Mon, 10 May 2021 02:01:25 +0200 Subject: [PATCH 004/114] BAEL-3682 specify accept header to fix ambiguity of message converters in case XML converter added --- .../java/com/baeldung/spring/WebConfig.java | 54 ++++++++----------- .../common/web/AbstractBasicLiveTest.java | 12 +++-- .../web/FooControllerAppIntegrationTest.java | 17 +++--- ...ooControllerCustomEtagIntegrationTest.java | 5 +- .../FooControllerWebLayerIntegrationTest.java | 19 ++++--- .../com/baeldung/web/FooPageableLiveTest.java | 5 +- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 13a9933fa6..4fce72a75f 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -5,7 +5,6 @@ import java.util.List; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; @@ -16,35 +15,25 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { - // @Override - // public void configureMessageConverters(final List> messageConverters) { - // messageConverters.add(new MappingJackson2HttpMessageConverter()); - // messageConverters.add(createXmlHttpMessageConverter()); - // } - // - // private HttpMessageConverter createXmlHttpMessageConverter() { - // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - // - // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - // xstreamMarshaller.setAutodetectAnnotations(true); - // xmlConverter.setMarshaller(xstreamMarshaller); - // xmlConverter.setUnmarshaller(xstreamMarshaller); - // - // return xmlConverter; - // } + @Override + public void configureMessageConverters(final List> messageConverters) { + messageConverters.add(new MappingJackson2HttpMessageConverter()); + messageConverters.add(createXmlHttpMessageConverter()); + } - // Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations - // @Bean - // public HttpMessageConverter createXmlHttpMessageConverter() { - // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - // - // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - // xstreamMarshaller.setAutodetectAnnotations(true); - // xmlConverter.setMarshaller(xstreamMarshaller); - // xmlConverter.setUnmarshaller(xstreamMarshaller); - // - // return xmlConverter; - // } + /** + * There is another possibility to add a message converter, see {@link ConverterExtensionsConfig} + */ + private HttpMessageConverter createXmlHttpMessageConverter() { + final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + + final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + xstreamMarshaller.setAutodetectAnnotations(true); + xmlConverter.setMarshaller(xstreamMarshaller); + xmlConverter.setUnmarshaller(xstreamMarshaller); + + return xmlConverter; + } // Etags @@ -52,16 +41,17 @@ public class WebConfig implements WebMvcConfigurer { // AbstractAnnotationConfigDispatcherServletInitializer#getServletFilters @Bean public FilterRegistrationBean shallowEtagHeaderFilter() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>( new ShallowEtagHeaderFilter()); + FilterRegistrationBean filterRegistrationBean = + new FilterRegistrationBean<>(new ShallowEtagHeaderFilter()); filterRegistrationBean.addUrlPatterns("/foos/*"); filterRegistrationBean.setName("etagFilter"); return filterRegistrationBean; } - + // We can also just declare the filter directly // @Bean // public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { // return new ShallowEtagHeaderFilter(); // } -} \ No newline at end of file +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java index ecf938be50..6e50f828de 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java @@ -24,6 +24,7 @@ import com.google.common.net.HttpHeaders; import io.restassured.RestAssured; import io.restassured.http.ContentType; import io.restassured.response.Response; +import org.springframework.http.MediaType; public abstract class AbstractBasicLiveTest extends AbstractLiveTest { @@ -36,7 +37,7 @@ public abstract class AbstractBasicLiveTest extends Abst @Test public void whenResourcesAreRetrievedPaged_then200IsReceived() { create(); - + final Response response = RestAssured.get(getURL() + "?page=0&size=10"); assertThat(response.getStatusCode(), is(200)); @@ -54,7 +55,8 @@ public abstract class AbstractBasicLiveTest extends Abst public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() { create(); - final Response response = RestAssured.get(getURL() + "?page=0&size=10"); + final Response response = RestAssured.given() + .accept(MediaType.APPLICATION_JSON_VALUE).get(getURL() + "?page=0&size=10"); assertFalse(response.body().as(List.class).isEmpty()); } @@ -64,7 +66,7 @@ public abstract class AbstractBasicLiveTest extends Abst create(); create(); create(); - + final Response response = RestAssured.get(getURL() + "?page=0&size=2"); final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); @@ -95,7 +97,7 @@ public abstract class AbstractBasicLiveTest extends Abst create(); create(); create(); - + final Response first = RestAssured.get(getURL() + "?page=0&size=2"); final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last"); @@ -104,7 +106,7 @@ public abstract class AbstractBasicLiveTest extends Abst final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); assertNull(uriToNextPage); } - + // etags @Test diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java index 5e8a190fb0..b1a84b47a7 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java @@ -11,13 +11,12 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; /** - * - * We'll start the whole context, but not the server. We'll mock the REST calls instead. - * + * We'll start the whole context, but not the server. We'll mock the REST calls instead. */ @RunWith(SpringRunner.class) @SpringBootTest @@ -31,16 +30,18 @@ public class FooControllerAppIntegrationTest { private IFooDao fooDao; @Before - public void setup(){ + public void setup() { this.fooDao.deleteAll(); } @Test public void whenFindPaginatedRequest_thenEmptyResponse() throws Exception { - this.mockMvc.perform(get("/foos").param("page", "0") - .param("size", "2")) - .andExpect(status().isOk()) - .andExpect(content().json("[]")); + this.mockMvc.perform(get("/foos") + .param("page", "0") + .param("size", "2") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().json("[]")); } } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java index 9e7b60ed8c..e472d308e8 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java @@ -40,7 +40,7 @@ public class FooControllerCustomEtagIntegrationTest { private static String createFooJson() throws Exception { return serializeFoo(new Foo(randomAlphabetic(6))); } - + private static Foo deserializeFoo(String fooJson) throws Exception { ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(fooJson, Foo.class); @@ -97,7 +97,8 @@ public class FooControllerCustomEtagIntegrationTest { .getResponse() .getHeader(HttpHeaders.LOCATION); ResultActions findOneResponse = this.mvc - .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX) + .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)); String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG); Foo createdFoo = deserializeFoo(findOneResponse.andReturn().getResponse().getContentAsString()); createdFoo.setName("updated name"); diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java index 4d4a274b1a..070625b7d4 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java @@ -20,6 +20,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; +import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @@ -30,7 +31,7 @@ import com.baeldung.web.exception.CustomException1; import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; /** - * + * * We'll start only the web layer. * */ @@ -54,20 +55,22 @@ public class FooControllerWebLayerIntegrationTest { doNothing().when(publisher) .publishEvent(any(PaginatedResultsRetrievedEvent.class)); - this.mockMvc.perform(get("/foos").param("page", "0") - .param("size", "2")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$",Matchers.hasSize(1))); + this.mockMvc.perform(get("/foos") + .param("page", "0") + .param("size", "2") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(1))); } - + @Test public void delete_forException_fromService() throws Exception { Mockito.when(service.findAll()).thenThrow(new CustomException1()); this.mockMvc.perform(get("/foos")).andDo(h -> { final Exception expectedException = h.getResolvedException(); Assert.assertTrue(expectedException instanceof CustomException1); - + }); } - + } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java index dc60c0e422..242fbb609e 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java @@ -11,6 +11,7 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -68,7 +69,9 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() { create(); - final Response response = RestAssured.get(getPageableURL() + "?page=0&size=10"); + final Response response = RestAssured.given() + .accept(MediaType.APPLICATION_JSON_VALUE) + .get(getPageableURL() + "?page=0&size=10"); assertFalse(response.body().as(List.class).isEmpty()); } From af009149dc7e624b2809069ba56dc967bd871820 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Mon, 10 May 2021 02:03:01 +0200 Subject: [PATCH 005/114] BAEL-3682 add sample of http message converter beans autoconfiguration --- .../spring/ConverterExtensionsConfig.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java new file mode 100644 index 0000000000..df673b3f03 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java @@ -0,0 +1,30 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; + +/** + * Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations. + * + * ATTENTION: Multiple converter registration of the same type most likely causes problem (serialize twice, etc.) + * Therefore, be sure to remove manually added XML message converter first then uncomment + * this @{@link org.springframework.context.annotation.Configuration} to use + */ +//@Configuration +public class ConverterExtensionsConfig { + + @Bean + public HttpMessageConverter createXmlHttpMessageConverter() { + final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + + final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + xstreamMarshaller.setAutodetectAnnotations(true); + xmlConverter.setMarshaller(xstreamMarshaller); + xmlConverter.setUnmarshaller(xstreamMarshaller); + + return xmlConverter; + } + +} From 7352ccf5b2e15d7dbdf9bac1dbd2d420f43b081d Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Wed, 26 May 2021 23:39:55 +0530 Subject: [PATCH 006/114] Adding code for BAEL-4957 - Spring validation in the service layer --- spring-service-layer-validation/.gitignore | 63 +++++++++++++++ spring-service-layer-validation/README.md | 12 +++ spring-service-layer-validation/pom.xml | 46 +++++++++++ .../SpringServiceLayerValidationApp.java | 13 ++++ .../controller/UserAccountController.java | 22 ++++++ .../servicevalidation/dao/UserAccountDao.java | 32 ++++++++ .../servicevalidation/domain/UserAccount.java | 77 +++++++++++++++++++ .../servicevalidation/domain/UserAddress.java | 17 ++++ .../service/UserAccountService.java | 44 +++++++++++ 9 files changed, 326 insertions(+) create mode 100644 spring-service-layer-validation/.gitignore create mode 100644 spring-service-layer-validation/README.md create mode 100644 spring-service-layer-validation/pom.xml create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/.gitignore b/spring-service-layer-validation/.gitignore new file mode 100644 index 0000000000..8f5ee06047 --- /dev/null +++ b/spring-service-layer-validation/.gitignore @@ -0,0 +1,63 @@ +# Created by https://www.gitignore.io/api/eclipse + +### Eclipse ### + +.metadata +target/ +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Eclipse Patch ### +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# End of https://www.gitignore.io/api/eclipse \ No newline at end of file diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md new file mode 100644 index 0000000000..674831d6a5 --- /dev/null +++ b/spring-service-layer-validation/README.md @@ -0,0 +1,12 @@ +## Spring Boot MVC + +This module contains articles about validation in Service layer of Spring Boot project. + +### Relevant Articles: + +- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) +- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) +- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) +- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) +- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) +- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-service-layer-validation/pom.xml b/spring-service-layer-validation/pom.xml new file mode 100644 index 0000000000..31ec757699 --- /dev/null +++ b/spring-service-layer-validation/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + com.baeldung.spring-service-layer-validation + spring-service-layer-validation + 0.0.1-SNAPSHOT + + + UTF-8 + 12 + 12 + + + + org.springframework.boot + spring-boot-starter-parent + 2.4.5 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.hibernate.validator + hibernate-validator + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java new file mode 100644 index 0000000000..ea80a5da33 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.servicevalidation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringServiceLayerValidationApp { + + public static void main(String[] args) { + SpringApplication.run(SpringServiceLayerValidationApp.class, args); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java new file mode 100644 index 0000000000..b558ed89c2 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.servicevalidation.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; +import com.baeldung.spring.servicevalidation.service.UserAccountService; + +@RestController +public class UserAccountController { + + @Autowired + private UserAccountService service; + + @PostMapping("/addUserAccount") + public Object addUserAccount(@RequestBody UserAccount userAccount) { + return service.addUserAccount(userAccount); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java new file mode 100644 index 0000000000..d170ceef58 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.servicevalidation.dao; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountDao { + + private Map DB = new HashMap(); + + public String addUserAccount(UserAccount useraccount) { + DB.put(useraccount.getName(), useraccount); + return "success"; + } + + public Collection getAllUserAccounts() { + + Collection list = DB.values(); + if(list.isEmpty()) { + list.addAll(DB.values()); + } + return list; + + } + + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java new file mode 100644 index 0000000000..5b0e795a8a --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java @@ -0,0 +1,77 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class UserAccount { + + @NotNull(message = "Password must be between 4 to 15 characters") + @Size(min = 4, max = 15) + private String password; + + @NotBlank(message = "Name must not be blank") + private String name; + + @Min(value = 18, message = "Age should not be less than 18") + private int age; + + @NotBlank(message = "Phone must not be blank") + private String phone; + + @Valid + @NotNull(message = "UserAddress must not be blank") + private UserAddress useraddress; + + public UserAddress getUseraddress() { + return useraddress; + } + + public void setUseraddress(UserAddress useraddress) { + this.useraddress = useraddress; + } + + public UserAccount() { + + } + + public UserAccount(String email, String password, String name, int age) { + this.password = password; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java new file mode 100644 index 0000000000..85e7dfc05c --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.constraints.NotBlank; +public class UserAddress { + + @NotBlank + private String countryCode; + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java new file mode 100644 index 0000000000..9a376fda6b --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.servicevalidation.service; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.dao.UserAccountDao; +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountService { + + @Autowired + private Validator validator; + + @Autowired + private UserAccountDao dao; + + public String addUserAccount(UserAccount useraccount) { + + Set> violations = validator.validate(useraccount); + + if (!violations.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (ConstraintViolation constraintViolation : violations) { + sb.append(constraintViolation.getMessage()); + } + + dao.addUserAccount(useraccount); + + throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); + } + + + + return "Account for " + useraccount.getName() + " Added!"; + } + +} From 4407da95c1ba2396d592c4be1e8f28535b0ab96b Mon Sep 17 00:00:00 2001 From: MicuEmerson Date: Wed, 2 Jun 2021 20:57:42 +0300 Subject: [PATCH 007/114] BAEL-4014 - added the code --- .../baeldung/cloud/openfeign/client/UserClient.java | 13 +++++++++++++ .../cloud/openfeign/config/FeignConfig.java | 12 ++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/UserClient.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/FeignConfig.java diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/UserClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/UserClient.java new file mode 100644 index 0000000000..9416bd30f0 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/UserClient.java @@ -0,0 +1,13 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.config.FeignConfig; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@FeignClient(name = "user-client", url="https://jsonplaceholder.typicode.com", configuration = FeignConfig.class) +public interface UserClient { + + @RequestMapping(value = "/users", method = RequestMethod.GET) + String getUsers(); +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/FeignConfig.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/FeignConfig.java new file mode 100644 index 0000000000..d51e97b9e4 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/FeignConfig.java @@ -0,0 +1,12 @@ +package com.baeldung.cloud.openfeign.config; + +import feign.Logger; +import org.springframework.context.annotation.Bean; + +public class FeignConfig { + + @Bean + Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } +} \ No newline at end of file From 9b4d965e3467a3f1c1f1969e24815b088191dc4b Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Mon, 7 Jun 2021 15:52:34 +0530 Subject: [PATCH 008/114] moving spring service layer validation code --- .../spring-boot-servicelayer-validation}/.gitignore | 0 .../spring-boot-servicelayer-validation/README.md | 4 ++++ .../spring-boot-servicelayer-validation}/pom.xml | 0 .../SpringServiceLayerValidationApp.java | 0 .../controller/UserAccountController.java | 0 .../spring/servicevalidation/dao/UserAccountDao.java | 0 .../spring/servicevalidation/domain/UserAccount.java | 0 .../spring/servicevalidation/domain/UserAddress.java | 0 .../service/UserAccountService.java | 0 spring-service-layer-validation/README.md | 12 ------------ 10 files changed, 4 insertions(+), 12 deletions(-) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/.gitignore (100%) create mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/README.md rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/pom.xml (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java (100%) delete mode 100644 spring-service-layer-validation/README.md diff --git a/spring-service-layer-validation/.gitignore b/spring-boot-modules/spring-boot-servicelayer-validation/.gitignore similarity index 100% rename from spring-service-layer-validation/.gitignore rename to spring-boot-modules/spring-boot-servicelayer-validation/.gitignore diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/README.md b/spring-boot-modules/spring-boot-servicelayer-validation/README.md new file mode 100644 index 0000000000..7c39135db6 --- /dev/null +++ b/spring-boot-modules/spring-boot-servicelayer-validation/README.md @@ -0,0 +1,4 @@ +## Spring Service Layer Validation + +This module contains articles about validation in Service layer of Spring Boot project. + diff --git a/spring-service-layer-validation/pom.xml b/spring-boot-modules/spring-boot-servicelayer-validation/pom.xml similarity index 100% rename from spring-service-layer-validation/pom.xml rename to spring-boot-modules/spring-boot-servicelayer-validation/pom.xml diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md deleted file mode 100644 index 674831d6a5..0000000000 --- a/spring-service-layer-validation/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Spring Boot MVC - -This module contains articles about validation in Service layer of Spring Boot project. - -### Relevant Articles: - -- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) -- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) -- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) -- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) -- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) -- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) From 90f629824f3abaa39ae440d03ed4c4fd51de6572 Mon Sep 17 00:00:00 2001 From: majewsk6 Date: Wed, 9 Jun 2021 09:06:15 +0200 Subject: [PATCH 009/114] BAEL-4269 3DES in Java --- .../com/baeldung/des/TripleDESUnitTest.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java new file mode 100644 index 0000000000..6e5df8e619 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/des/TripleDESUnitTest.java @@ -0,0 +1,90 @@ +package com.baeldung.des; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +public class TripleDESUnitTest { + + @Test + public void given3DesKey_whenEncryptAndDecryptString_thenCompareResults() throws Exception { + byte[] secretKey = "9mng65v8jf4lxn93nabf981m".getBytes(); + byte[] iv = "a76nb5h9".getBytes(); + + String secretMessage = "Baeldung secret message"; + + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "DESede"); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); + encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); + byte[] secretMessagesBytes = secretMessage.getBytes(StandardCharsets.UTF_8); + byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessagesBytes); + + Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); + decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); + byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes); + String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8); + + Assertions.assertEquals(secretMessage, decryptedMessage); + } + + @Test + public void given3DesKey_whenEncryptAndDecryptFile_thenCompareResults() throws Exception { + byte[] secretKey = "9mng65v8jf4lxn93nabf981m".getBytes(); + byte[] iv = "a76nb5h9".getBytes(); + + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "DESede"); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + + String originalContent = "some secret message"; + Path tempFile = Files.createTempFile("temp", "txt"); + writeString(tempFile, originalContent); + + byte[] fileBytes = Files.readAllBytes(tempFile); + Cipher encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); + encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); + byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes); + try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) { + stream.write(encryptedFileBytes); + } + + encryptedFileBytes = Files.readAllBytes(tempFile); + Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); + decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); + byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes); + try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) { + stream.write(decryptedFileBytes); + } + + String fileContent = readString(tempFile); + + Assertions.assertEquals(originalContent, fileContent); + } + + private void writeString(Path path, String content) throws Exception { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + writer.write(content); + } + } + + private String readString(Path path) throws Exception { + StringBuilder resultStringBuilder = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new FileReader(path.toFile()))) { + String line; + while ((line = br.readLine()) != null) { + resultStringBuilder.append(line); + } + } + return resultStringBuilder.toString(); + } +} From 08e96defa6b514f6afa7e3be2d611b359cd71aee Mon Sep 17 00:00:00 2001 From: akhil90s <46933461+akhil90s@users.noreply.github.com> Date: Fri, 11 Jun 2021 09:38:03 +0530 Subject: [PATCH 010/114] Deployment Vs StatefulSet --- .../Deployment/Deployment.yaml | 54 +++++++++++++++++++ .../Deployment/PersitantVoulumeClaim.yaml | 11 ++++ .../Deployment/Service.yaml | 12 +++++ .../StatefulSets/PersistantVolumeClaim.yaml | 10 ++++ .../StatefulSets/Service.yaml | 13 +++++ .../StatefulSets/StatefulSet.yaml | 28 ++++++++++ 6 files changed, 128 insertions(+) create mode 100644 kubernetes/Deployment_Vs_StatefulSet/Deployment/Deployment.yaml create mode 100644 kubernetes/Deployment_Vs_StatefulSet/Deployment/PersitantVoulumeClaim.yaml create mode 100644 kubernetes/Deployment_Vs_StatefulSet/Deployment/Service.yaml create mode 100644 kubernetes/Deployment_Vs_StatefulSet/StatefulSets/PersistantVolumeClaim.yaml create mode 100644 kubernetes/Deployment_Vs_StatefulSet/StatefulSets/Service.yaml create mode 100644 kubernetes/Deployment_Vs_StatefulSet/StatefulSets/StatefulSet.yaml diff --git a/kubernetes/Deployment_Vs_StatefulSet/Deployment/Deployment.yaml b/kubernetes/Deployment_Vs_StatefulSet/Deployment/Deployment.yaml new file mode 100644 index 0000000000..d463dd6dee --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/Deployment/Deployment.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-app-deployment +spec: + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 2 + maxUnavailable: 1 + selector: + matchLabels: + app: web-app + replicas: 3 + template: + metadata: + labels: + app: web-app + spec: + containers: + - name: web-app + image: hello-world:nanoserver-1809 + volumeMounts: + - name: counter + mountPath: /app/ + volumes: + - name: counter + persistentVolumeClaim: + claimName: counter +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: counter +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 50Mi + storageClassName: default +--- +apiVersion: v1 +kind: Service +metadata: + name: web-app-service +spec: + ports: + - name: http + port: 80 + nodePort: 30080 + selector: + name: web-app + type: NodePort diff --git a/kubernetes/Deployment_Vs_StatefulSet/Deployment/PersitantVoulumeClaim.yaml b/kubernetes/Deployment_Vs_StatefulSet/Deployment/PersitantVoulumeClaim.yaml new file mode 100644 index 0000000000..99bbb5d555 --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/Deployment/PersitantVoulumeClaim.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: counter +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 50Mi + storageClassName: default diff --git a/kubernetes/Deployment_Vs_StatefulSet/Deployment/Service.yaml b/kubernetes/Deployment_Vs_StatefulSet/Deployment/Service.yaml new file mode 100644 index 0000000000..eabb12c0e0 --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/Deployment/Service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: web-app-service +spec: + ports: + - name: http + port: 80 + nodePort: 30080 + selector: + name: web-app + type: NodePort diff --git a/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/PersistantVolumeClaim.yaml b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/PersistantVolumeClaim.yaml new file mode 100644 index 0000000000..59f137cff1 --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/PersistantVolumeClaim.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi diff --git a/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/Service.yaml b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/Service.yaml new file mode 100644 index 0000000000..80e5b50665 --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/Service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + app: nginx +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: nginx diff --git a/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/StatefulSet.yaml b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/StatefulSet.yaml new file mode 100644 index 0000000000..4ff4baca8c --- /dev/null +++ b/kubernetes/Deployment_Vs_StatefulSet/StatefulSets/StatefulSet.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: web +spec: + selector: + matchLabels: + app: nginx + serviceName: "nginx" + replicas: 3 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: www + mountPath: /usr/share/nginx/html + volumes: + - name: www + persistentVolumeClaim: + claimName: myclaim From 8090117cb6536dc71597d6a3a359dccc54b7ddb7 Mon Sep 17 00:00:00 2001 From: "Amitabh.Tiwari" Date: Tue, 15 Jun 2021 20:09:17 +0530 Subject: [PATCH 011/114] BAEL-4960: Test for conversion --- .../StringToBigIntegerUnitTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java new file mode 100644 index 0000000000..d3b6467eab --- /dev/null +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.stringtobybiginteger; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; + +import org.junit.Test; + +public class StringToBigIntegerUnitTest { + + @Test + public void whenGetStringWithOutRadix_thenOK() { + final String inputString = "878"; + BigInteger result = new BigInteger(inputString); + assertEquals("878", result.toString()); + } + + @Test + public void whenGetStringWithRadix_thenOK() { + final String inputString = "290f98"; + BigInteger result = new BigInteger(inputString, 16); + assertEquals("2690968", result.toString()); + } + + @Test(expected = NumberFormatException.class) + public void whenGetStringWithOutRadix_thenThrowError() { + final String inputString = "290f98"; + new BigInteger(inputString); + } + + @Test(expected = NumberFormatException.class) + public void whenGetStringWithRadix_thenThrowError() { + final String inputString = "Hello Baeldung"; + new BigInteger(inputString, 7); + } + + @Test + public void whenGetStringUsingByte_thenOk() { + final String inputString = "Hello Baeldung"; + byte[] inputStringBytes = inputString.getBytes(); + BigInteger result = new BigInteger(inputStringBytes); + assertEquals("Hello Baeldung", new String(result.toByteArray())); + } +} From 625676f7cbdde890937a53d3f0219e08de1bd311 Mon Sep 17 00:00:00 2001 From: "Amitabh.Tiwari" Date: Tue, 15 Jun 2021 20:13:37 +0530 Subject: [PATCH 012/114] Removal of unwanted spaces --- .../StringToBigIntegerUnitTest.java | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java index d3b6467eab..b535797d44 100644 --- a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java @@ -7,38 +7,38 @@ import java.math.BigInteger; import org.junit.Test; public class StringToBigIntegerUnitTest { - - @Test - public void whenGetStringWithOutRadix_thenOK() { - final String inputString = "878"; - BigInteger result = new BigInteger(inputString); - assertEquals("878", result.toString()); - } - @Test - public void whenGetStringWithRadix_thenOK() { - final String inputString = "290f98"; - BigInteger result = new BigInteger(inputString, 16); - assertEquals("2690968", result.toString()); - } + @Test + public void whenGetStringWithOutRadix_thenOK() { + final String inputString = "878"; + BigInteger result = new BigInteger(inputString); + assertEquals("878", result.toString()); + } - @Test(expected = NumberFormatException.class) - public void whenGetStringWithOutRadix_thenThrowError() { - final String inputString = "290f98"; - new BigInteger(inputString); - } + @Test + public void whenGetStringWithRadix_thenOK() { + final String inputString = "290f98"; + BigInteger result = new BigInteger(inputString, 16); + assertEquals("2690968", result.toString()); + } - @Test(expected = NumberFormatException.class) - public void whenGetStringWithRadix_thenThrowError() { - final String inputString = "Hello Baeldung"; - new BigInteger(inputString, 7); - } + @Test(expected = NumberFormatException.class) + public void whenGetStringWithOutRadix_thenThrowError() { + final String inputString = "290f98"; + new BigInteger(inputString); + } - @Test - public void whenGetStringUsingByte_thenOk() { - final String inputString = "Hello Baeldung"; - byte[] inputStringBytes = inputString.getBytes(); - BigInteger result = new BigInteger(inputStringBytes); - assertEquals("Hello Baeldung", new String(result.toByteArray())); - } + @Test(expected = NumberFormatException.class) + public void whenGetStringWithRadix_thenThrowError() { + final String inputString = "Hello Baeldung"; + new BigInteger(inputString, 7); + } + + @Test + public void whenGetStringUsingByte_thenOk() { + final String inputString = "Hello Baeldung"; + byte[] inputStringBytes = inputString.getBytes(); + BigInteger result = new BigInteger(inputStringBytes); + assertEquals("Hello Baeldung", new String(result.toByteArray())); + } } From 74f1bfefa25ef57bbac3abb080abdcef18b9d4e3 Mon Sep 17 00:00:00 2001 From: sharifi Date: Sat, 19 Jun 2021 13:29:35 +0430 Subject: [PATCH 013/114] BAEL-4956: add source code for describing REST API in swagger --- .../com/baeldung/apiswagger/Application.java | 12 +++++++++ .../config/SwaggerConfiguration.java | 26 +++++++++++++++++++ .../apiswagger/controller/BookController.java | 21 +++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/Application.java create mode 100644 spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/config/SwaggerConfiguration.java create mode 100644 spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/controller/BookController.java diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/Application.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/Application.java new file mode 100644 index 0000000000..9232152b5b --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.apiswagger; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication() +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/config/SwaggerConfiguration.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/config/SwaggerConfiguration.java new file mode 100644 index 0000000000..d9f51698c3 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/config/SwaggerConfiguration.java @@ -0,0 +1,26 @@ +package com.baeldung.apiswagger.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.Tag; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@Configuration +public class SwaggerConfiguration { + + public static final String BOOK_TAG = "book service"; + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + .tags(new Tag(BOOK_TAG, "the book API with description api tag")); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/controller/BookController.java b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/controller/BookController.java new file mode 100644 index 0000000000..394c640751 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger/src/main/java/com/baeldung/apiswagger/controller/BookController.java @@ -0,0 +1,21 @@ +package com.baeldung.apiswagger.controller; + +import com.baeldung.apiswagger.config.SwaggerConfiguration; +import io.swagger.annotations.Api; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + +@RestController +@RequestMapping("/api/book") +@Api(tags = {SwaggerConfiguration.BOOK_TAG}) +public class BookController { + + @GetMapping("/") + public List getBooks() { + return Arrays.asList("book1", "book2"); + } +} \ No newline at end of file From 618cdbdcedd77fb6690b151c8d53d0d587337a5d Mon Sep 17 00:00:00 2001 From: sharifi Date: Sat, 19 Jun 2021 13:29:50 +0430 Subject: [PATCH 014/114] BAEL-4956: add source code for describng REST API in openapi --- .../com/baeldung/tagopenapi/Application.java | 12 +++++++++++ .../baeldung/tagopenapi/config/OpenApi.java | 20 +++++++++++++++++++ .../tagopenapi/controller/BookController.java | 20 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/Application.java create mode 100644 spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/config/OpenApi.java create mode 100644 spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/controller/BookController.java diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/Application.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/Application.java new file mode 100644 index 0000000000..3141428514 --- /dev/null +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.tagopenapi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication() +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/config/OpenApi.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/config/OpenApi.java new file mode 100644 index 0000000000..780b202d3c --- /dev/null +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/config/OpenApi.java @@ -0,0 +1,20 @@ +package com.baeldung.tagopenapi.config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; + +public class OpenApi { + + @Bean + public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) { + return new OpenAPI().info(new Info().title("Controller API") + .version(appVersion) + .description("This is a sample server created using springdocs - a library for OpenAPI 3 with spring boot.") + .termsOfService("http://swagger.io/terms/") + .license(new License().name("Apache 2.0") + .url("http://springdoc.org"))); + } +} diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/controller/BookController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/controller/BookController.java new file mode 100644 index 0000000000..3c81c1cee7 --- /dev/null +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/tagopenapi/controller/BookController.java @@ -0,0 +1,20 @@ +package com.baeldung.tagopenapi.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + +@RestController +@RequestMapping("/api/book") +@Tag(name = "book service", description = "the book API with description tag annotation") +public class BookController { + + @GetMapping("/") + public List getBooks() { + return Arrays.asList("book1", "book2"); + } +} From 039416f0eb392976093a2b74a7f0c7fb7c14062c Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Sun, 20 Jun 2021 04:42:31 +0200 Subject: [PATCH 015/114] BAEL-3682 remove setAutodetectAnnotations in favor of aligning with the article's code samples --- .../main/java/com/baeldung/spring/ConverterExtensionsConfig.java | 1 - .../src/main/java/com/baeldung/spring/WebConfig.java | 1 - 2 files changed, 2 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java index df673b3f03..42bf50ac5f 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/ConverterExtensionsConfig.java @@ -20,7 +20,6 @@ public class ConverterExtensionsConfig { final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xstreamMarshaller.setAutodetectAnnotations(true); xmlConverter.setMarshaller(xstreamMarshaller); xmlConverter.setUnmarshaller(xstreamMarshaller); diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 4fce72a75f..69724fda29 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -28,7 +28,6 @@ public class WebConfig implements WebMvcConfigurer { final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xstreamMarshaller.setAutodetectAnnotations(true); xmlConverter.setMarshaller(xstreamMarshaller); xmlConverter.setUnmarshaller(xstreamMarshaller); From 5b59b7f6524b431bd693b6e82a8741cdbee4b1b1 Mon Sep 17 00:00:00 2001 From: Yavuz Tas Date: Sun, 20 Jun 2021 04:46:14 +0200 Subject: [PATCH 016/114] BAEL-3682 integrate missing http message converters test from spring-web-modules/spring-rest-simple module --- .../web/FooMessageConvertersLiveTest.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/FooMessageConvertersLiveTest.java diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooMessageConvertersLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooMessageConvertersLiveTest.java new file mode 100644 index 0000000000..9b1a9e9733 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooMessageConvertersLiveTest.java @@ -0,0 +1,149 @@ +package com.baeldung.web; + +import static com.baeldung.Consts.APPLICATION_PORT; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import com.baeldung.common.web.AbstractLiveTest; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.ConfigIntegrationTest; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.web.client.RestTemplate; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +public class FooMessageConvertersLiveTest extends AbstractLiveTest { + + private static final String BASE_URI = "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/"; + + public FooMessageConvertersLiveTest() { + super(Foo.class); + } + + @Override + public final void create() { + create(new Foo(randomAlphabetic(6))); + } + + @Override + public final String createAsUri() { + return createAsUri(new Foo(randomAlphabetic(6))); + } + + @Before + public void setup(){ + create(); + } + + /** + * Without specifying Accept Header, uses the default response from the + * server (in this case json) + */ + @Test + public void whenRetrievingAFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + final Foo resource = restTemplate.getForObject(URI, Foo.class, "1"); + + assertThat(resource, notNullValue()); + } + + @Test + public void givenConsumingXml_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setMessageConverters(getXmlMessageConverters()); + + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML)); + final HttpEntity entity = new HttpEntity<>(headers); + + final ResponseEntity + response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); + final Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + + private List> getXmlMessageConverters() { + final XStreamMarshaller marshaller = new XStreamMarshaller(); + marshaller.setAnnotatedClasses(Foo.class); + final MarshallingHttpMessageConverter marshallingConverter = new MarshallingHttpMessageConverter(marshaller); + + final List> converters = new ArrayList<>(); + converters.add(marshallingConverter); + return converters; + } + + @Test + public void givenConsumingJson_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setMessageConverters(getJsonMessageConverters()); + + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + final HttpEntity entity = new HttpEntity(headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); + final Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + + private List> getJsonMessageConverters() { + final List> converters = new ArrayList<>(); + converters.add(new MappingJackson2HttpMessageConverter()); + return converters; + } + + @Test + public void givenConsumingXml_whenWritingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos"; + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setMessageConverters(getJsonAndXmlMessageConverters()); + + final Foo resource = new Foo("jason"); + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType((MediaType.APPLICATION_XML)); + final HttpEntity entity = new HttpEntity<>(resource, headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.POST, entity, Foo.class); + final Foo fooResponse = response.getBody(); + + assertThat(fooResponse, notNullValue()); + assertEquals(resource.getName(), fooResponse.getName()); + } + + private List> getJsonAndXmlMessageConverters() { + final List> converters = getJsonMessageConverters(); + converters.addAll(getXmlMessageConverters()); + return converters; + } + +} From b47e749a4afd9d84860a9636738a93ddf8cf4a0f Mon Sep 17 00:00:00 2001 From: Jacek Polom Date: Sun, 20 Jun 2021 21:01:03 +0200 Subject: [PATCH 017/114] BAEL-4447 Enable logging for Apache HttpClient --- httpclient-2/pom.xml | 6 ++++ .../ApacheHttpClient5UnitTest.java | 29 +++++++++++++++++++ .../ApacheHttpClientUnitTest.java | 6 ++-- httpclient-2/src/test/resources/logback.xml | 15 ++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java create mode 100644 httpclient-2/src/test/resources/logback.xml diff --git a/httpclient-2/pom.xml b/httpclient-2/pom.xml index 881b0407c3..a6b2ede900 100644 --- a/httpclient-2/pom.xml +++ b/httpclient-2/pom.xml @@ -26,6 +26,11 @@ + + org.apache.httpcomponents.client5 + httpclient5 + ${httpclient5.version} + org.springframework.boot @@ -63,6 +68,7 @@ 4.5.8 + 5.1 11 11 2.1.7.RELEASE diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java new file mode 100644 index 0000000000..35b21789ef --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.httpclient.readresponsebodystring; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class ApacheHttpClient5UnitTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + public static final String DUMMY_URL = "https://postman-echo.com/get"; + + @Test + public void whenUseApacheHttpClient_thenCorrect() throws IOException, ParseException { + HttpGet request = new HttpGet(DUMMY_URL); + + try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) { + HttpEntity entity = response.getEntity(); + logger.debug("Response -> {}", EntityUtils.toString(entity)); + } + } +} \ No newline at end of file diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java index 5a638b2bd5..7625b415f2 100644 --- a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java @@ -7,10 +7,13 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; public class ApacheHttpClientUnitTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); public static final String DUMMY_URL = "https://postman-echo.com/get"; @Test @@ -19,8 +22,7 @@ public class ApacheHttpClientUnitTest { try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) { HttpEntity entity = response.getEntity(); - String result = EntityUtils.toString(entity); - System.out.println("Response -> " + result); + logger.debug("Response -> {}", EntityUtils.toString(entity)); } } } diff --git a/httpclient-2/src/test/resources/logback.xml b/httpclient-2/src/test/resources/logback.xml new file mode 100644 index 0000000000..366a94e86e --- /dev/null +++ b/httpclient-2/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + %date [%level] %logger - %msg %n + + + + + + + + + + + \ No newline at end of file From b7f31513f8150c879c70bfe1ccccb04487f521f6 Mon Sep 17 00:00:00 2001 From: "Amitabh.Tiwari" Date: Wed, 23 Jun 2021 10:22:35 +0530 Subject: [PATCH 018/114] Corrected test as per review comments --- .../stringtobybiginteger/StringToBigIntegerUnitTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java index b535797d44..54c9617718 100644 --- a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java @@ -30,13 +30,13 @@ public class StringToBigIntegerUnitTest { @Test(expected = NumberFormatException.class) public void whenGetStringWithRadix_thenThrowError() { - final String inputString = "Hello Baeldung"; + final String inputString = "290f98"; new BigInteger(inputString, 7); } @Test public void whenGetStringUsingByte_thenOk() { - final String inputString = "Hello Baeldung"; + final String inputString = "290f98"; byte[] inputStringBytes = inputString.getBytes(); BigInteger result = new BigInteger(inputStringBytes); assertEquals("Hello Baeldung", new String(result.toByteArray())); From e746beee454488a0f30fa1ad49ac1fd981076e99 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 26 Jun 2021 15:59:38 +0530 Subject: [PATCH 019/114] JAVA-5933: Analyse bean overriding fix in modules - Part 1 --- .../src/main/java/com/baeldung/thymeleaf/articles/Article.java | 2 +- .../com/baeldung/thymeleaf/articles/ArticlesController.java | 2 +- .../src/main/resources/application.properties | 3 +-- vaadin/src/main/resources/application.properties | 2 -- 4 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 vaadin/src/main/resources/application.properties diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java index 9b01328e45..efab434e31 100644 --- a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java @@ -1,4 +1,4 @@ -package main.java.com.baeldung.thymeleaf.articles; +package com.baeldung.thymeleaf.articles; public class Article { diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java index cfbf0fcaa6..e3972ffb51 100644 --- a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java @@ -1,4 +1,4 @@ -package main.java.com.baeldung.thymeleaf.articles; +package com.baeldung.thymeleaf.articles; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties b/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties index 75770808da..730dded1b7 100644 --- a/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties +++ b/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties @@ -2,5 +2,4 @@ spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/vaadin/src/main/resources/application.properties b/vaadin/src/main/resources/application.properties deleted file mode 100644 index 1cb7086b82..0000000000 --- a/vaadin/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Vaadin supports spring-boot 2.1 properly from V8 onwards (according to this comment https://github.com/vaadin/spring/issues/331#issuecomment-435128475) -spring.main.allow-bean-definition-overriding=true \ No newline at end of file From 23909a83491f3f24239cd96cdaa8e5d66baedcfd Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 26 Jun 2021 18:28:07 +0530 Subject: [PATCH 020/114] JAVA-5934: Analyse bean overriding fix in modules - Part 2 --- .../src/main/resources/application.properties | 1 - .../spring-boot-data/src/main/resources/application.properties | 2 +- .../src/main/resources/application.properties | 1 - .../src/main/resources/application.properties | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 spring-boot-modules/spring-boot-artifacts/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-boot-artifacts/src/main/resources/application.properties b/spring-boot-modules/spring-boot-artifacts/src/main/resources/application.properties deleted file mode 100644 index 709574239b..0000000000 --- a/spring-boot-modules/spring-boot-artifacts/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties index 6378a48506..292fb8dc9f 100644 --- a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties @@ -6,7 +6,7 @@ spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password= -spring.main.allow-bean-definition-overriding=true +#spring.main.allow-bean-definition-overriding=true javers.mappingStyle=FIELD javers.algorithm=SIMPLE javers.commitIdGenerator=synchronized_sequence diff --git a/spring-boot-modules/spring-boot-deployment/src/main/resources/application.properties b/spring-boot-modules/spring-boot-deployment/src/main/resources/application.properties index 27b7915cff..2bf15543f0 100644 --- a/spring-boot-modules/spring-boot-deployment/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-deployment/src/main/resources/application.properties @@ -3,5 +3,4 @@ management.metrics.enable.root=true management.metrics.enable.jvm=true management.endpoint.restart.enabled=true spring.datasource.jmx-enabled=false -spring.main.allow-bean-definition-overriding=true management.endpoint.shutdown.enabled=true \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties b/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties index 3d6f37230c..4ffb414e92 100644 --- a/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties @@ -3,6 +3,5 @@ management.metrics.enable.root=true management.metrics.enable.jvm=true management.endpoint.restart.enabled=true spring.datasource.tomcat.jmx-enabled=false -spring.main.allow-bean-definition-overriding=true management.endpoint.shutdown.enabled=true spring.config.import=file:./additional.properties,optional:file:/Users/home/config/jdbc.properties \ No newline at end of file From c51a520eddfdb20b8f3e413f54ffc0d6fca03a98 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 26 Jun 2021 18:29:13 +0530 Subject: [PATCH 021/114] JAVA-5934: Analyse bean overriding fix in modules - Part 2 --- .../spring-boot-data/src/main/resources/application.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties index 292fb8dc9f..969464a41c 100644 --- a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties @@ -6,7 +6,6 @@ spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password= -#spring.main.allow-bean-definition-overriding=true javers.mappingStyle=FIELD javers.algorithm=SIMPLE javers.commitIdGenerator=synchronized_sequence From da30dde62423797cff6a52c7c34654801ce5f681 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Mon, 28 Jun 2021 00:23:18 +0530 Subject: [PATCH 022/114] JAVA-5975 Resolved test errors in jee-7 (#10973) --- jee-7/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jee-7/pom.xml b/jee-7/pom.xml index 925d79728e..2030a769b0 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -487,7 +487,7 @@ 1.0.0 - 1.0.0 + 1.0-edr2 1.8 3.0.0 7.0 From 67f11db2110b5288e4c7b534f022cb1bf8758b8b Mon Sep 17 00:00:00 2001 From: "Amitabh.Tiwari" Date: Mon, 28 Jun 2021 18:57:48 +0530 Subject: [PATCH 023/114] Corrected the tests --- .../stringtobybiginteger/StringToBigIntegerUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java index 54c9617718..8d47d72a0e 100644 --- a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java @@ -39,6 +39,6 @@ public class StringToBigIntegerUnitTest { final String inputString = "290f98"; byte[] inputStringBytes = inputString.getBytes(); BigInteger result = new BigInteger(inputStringBytes); - assertEquals("Hello Baeldung", new String(result.toByteArray())); + assertEquals("290f98", new String(result.toByteArray())); } } From 2cf52853fa36746f00791e8c728fc623a4297130 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Mon, 28 Jun 2021 18:42:50 +0300 Subject: [PATCH 024/114] BAEL-4913 - Spring Native (#10942) * BAEL-4913 - Spring Native * BAEL-4913 - review commit --- pom.xml | 3 +- spring-native/pom-nativeimage.xml | 122 ++++++++++++++++++ spring-native/pom.xml | 80 ++++++++++++ .../springnativeintro/SpringNativeApp.java | 9 ++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 spring-native/pom-nativeimage.xml create mode 100644 spring-native/pom.xml create mode 100644 spring-native/src/main/java/com/baeldung/springnativeintro/SpringNativeApp.java diff --git a/pom.xml b/pom.xml index eac534697a..477ae66454 100644 --- a/pom.xml +++ b/pom.xml @@ -660,6 +660,7 @@ spring-mobile spring-mockito + spring-native spring-protobuf spring-quartz @@ -1117,7 +1118,7 @@ spring-mobile spring-mockito - + spring-native spring-protobuf spring-quartz diff --git a/spring-native/pom-nativeimage.xml b/spring-native/pom-nativeimage.xml new file mode 100644 index 0000000000..1b2cc3944a --- /dev/null +++ b/spring-native/pom-nativeimage.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + baeldung-spring-native + baeldung-spring-native + jar + Intro to Spring Native + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + spring-release + Spring release + https://repo.spring.io/release + + + + + + spring-release + Spring release + https://repo.spring.io/release + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring-boot.version} + pom + + + org.springframework.experimental + spring-native + ${spring-native.version} + + + org.springframework.experimental + spring-aot + ${spring-native.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.springframework.experimental + spring-aot-maven-plugin + ${spring-native.version} + + + test-generate + + test-generate + + + + generate + + generate + + + + + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native-maven-plugin.version} + + + build-native + + build + + package + + + + + org.springframework.boot + spring-boot-maven-plugin + + exec + + + + + + + + + 2.5.1 + 0.10.0 + 0.9.0 + 1.8 + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/spring-native/pom.xml b/spring-native/pom.xml new file mode 100644 index 0000000000..1064800352 --- /dev/null +++ b/spring-native/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + baeldung-spring-native + baeldung-spring-native + jar + Intro to Spring Native + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + spring-release + Spring release + https://repo.spring.io/release + + + + + + spring-release + Spring release + https://repo.spring.io/release + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring-boot.version} + pom + + + org.springframework.experimental + spring-native + ${spring-native.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + ${builder} + + true + + IF_NOT_PRESENT + + + + + org.springframework.experimental + spring-aot-maven-plugin + ${spring-native.version} + + + + + + paketobuildpacks/builder:tiny + 2.5.1 + 0.10.0 + 1.8 + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/spring-native/src/main/java/com/baeldung/springnativeintro/SpringNativeApp.java b/spring-native/src/main/java/com/baeldung/springnativeintro/SpringNativeApp.java new file mode 100644 index 0000000000..fa54d34f9f --- /dev/null +++ b/spring-native/src/main/java/com/baeldung/springnativeintro/SpringNativeApp.java @@ -0,0 +1,9 @@ +package com.baeldung.springnativeintro; + +public class SpringNativeApp { + + public static void main(String[] args) { + System.out.println("Hello, World! This is a Baledung Spring Native Application"); + } + +} From 0d722c1d90d6159fbd50e7065920c0d3460ca53c Mon Sep 17 00:00:00 2001 From: Diego Torres Date: Tue, 29 Jun 2021 04:46:32 -0400 Subject: [PATCH 025/114] [uuid] diegotorres/dtorres.py@gmail.com Improvements for UUIDv5 generation (#10978) * [uuid] Added method to generate UUID identifiers for version 5 Signed-off-by: Diego Torres * [uuid] Small improvements for UUIDv5 generation Signed-off-by: Diego Torres --- .../java/com/baeldung/uuid/UUIDGenerator.java | 19 ++++++------------- .../baeldung/uuid/UUIDGeneratorUnitTest.java | 4 ++-- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index 49d43c38a2..54de1f95c6 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -176,8 +176,8 @@ public class UUIDGenerator { byte[] hash = md.digest(bytes); - long msb = peekLong(hash, 0, ByteOrder.BIG_ENDIAN); - long lsb = peekLong(hash, 8, ByteOrder.BIG_ENDIAN); + long msb = getLeastAndMostSignificantBitsVersion5(hash, 0); + long lsb = getLeastAndMostSignificantBitsVersion5(hash, 8); // Set the version field msb &= ~(0xfL << 12); msb |= ((long) 5) << 12; @@ -191,18 +191,11 @@ public class UUIDGenerator { } } - private static long peekLong(final byte[] src, final int offset, final ByteOrder order) { + private static long getLeastAndMostSignificantBitsVersion5(final byte[] src, final int offset) { long ans = 0; - if (order == ByteOrder.BIG_ENDIAN) { - for (int i = offset; i < offset + 8; i += 1) { - ans <<= 8; - ans |= src[i] & 0xffL; - } - } else { - for (int i = offset + 7; i >= offset; i -= 1) { - ans <<= 8; - ans |= src[i] & 0xffL; - } + for (int i = offset + 7; i >= offset; i -= 1) { + ans <<= 8; + ans |= src[i] & 0xffL; } return ans; } diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java index b2ca979c83..cf0d7656ff 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java @@ -63,11 +63,11 @@ class UUIDGeneratorUnitTest { } @Test - public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com_without_namespace() throws UnsupportedEncodingException { + public void version_5_UUID_is_correctly_generated_for_domain_baeldung_name() { UUID uuid = UUIDGenerator.generateType5UUID("baeldung.com"); - assertEquals("a3c27ab0-2b46-55ef-b50e-0e5c57bfea94", uuid.toString()); + assertEquals("efd5462b-b07a-52a3-94ea-bf575c0e0e75", uuid.toString()); assertEquals(5, uuid.version()); assertEquals(2, uuid.variant()); } From 2c9bb8f04dbf13d9f535c40f0d961043b2ba6fbd Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 29 Jun 2021 22:48:40 +0530 Subject: [PATCH 026/114] JAVA-5975 Disabled spring-security-web-react, will be fixing in JAVA-6216 (#10981) --- spring-security-modules/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index e482a67a0e..5847d6f28d 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -38,7 +38,7 @@ spring-security-web-mvc-custom spring-security-web-mvc spring-security-web-persistent-login - spring-security-web-react + spring-security-web-rest-basic-auth spring-security-web-rest-custom spring-security-web-rest @@ -49,4 +49,4 @@ spring-social-login - \ No newline at end of file + From ec43ac575ab31408e7c8cf27f3860652f519fc5a Mon Sep 17 00:00:00 2001 From: sharifi Date: Wed, 30 Jun 2021 19:57:34 +0430 Subject: [PATCH 027/114] bael-4843: add log4j2.xml --- .../log4j2/src/main/resources/log4j2.xml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 logging-modules/log4j2/src/main/resources/log4j2.xml diff --git a/logging-modules/log4j2/src/main/resources/log4j2.xml b/logging-modules/log4j2/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..160981d819 --- /dev/null +++ b/logging-modules/log4j2/src/main/resources/log4j2.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 2b64a6a2633ff792be2b9cb59134c4d68e8d9e47 Mon Sep 17 00:00:00 2001 From: sharifi Date: Thu, 1 Jul 2021 14:08:12 +0430 Subject: [PATCH 028/114] bael-4843: add syslog appender to log4j conf --- .../src/main/resources/log4j2-spring.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/log4j2-spring.xml b/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/log4j2-spring.xml index b08cd2d22d..77a2074b30 100644 --- a/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/log4j2-spring.xml +++ b/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/log4j2-spring.xml @@ -22,6 +22,10 @@ + + + @@ -29,6 +33,7 @@ + From 1b4c50c7c1cfbe565d8d580d56173302133ce9aa Mon Sep 17 00:00:00 2001 From: sharifi Date: Thu, 1 Jul 2021 14:08:28 +0430 Subject: [PATCH 029/114] bael-4843: remove file --- .../log4j2/src/main/resources/log4j2.xml | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 logging-modules/log4j2/src/main/resources/log4j2.xml diff --git a/logging-modules/log4j2/src/main/resources/log4j2.xml b/logging-modules/log4j2/src/main/resources/log4j2.xml deleted file mode 100644 index 160981d819..0000000000 --- a/logging-modules/log4j2/src/main/resources/log4j2.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 002c0ef4e85d4fcc291f4294645295334dec6d18 Mon Sep 17 00:00:00 2001 From: sharifi Date: Thu, 1 Jul 2021 14:08:53 +0430 Subject: [PATCH 030/114] bael-4843: add main spring boot class and logger --- .../syslog/SpringBootSyslogApplication.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/syslog/SpringBootSyslogApplication.java diff --git a/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/syslog/SpringBootSyslogApplication.java b/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/syslog/SpringBootSyslogApplication.java new file mode 100644 index 0000000000..56c3b62c5d --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/syslog/SpringBootSyslogApplication.java @@ -0,0 +1,23 @@ +package com.baeldung.syslog; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootSyslogApplication { + + private static final Logger logger = LogManager.getLogger(SpringBootSyslogApplication.class); + + public static void main(String[] args) { + SpringApplication.run(SpringBootSyslogApplication.class, args); + + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + logger.warn("Warn log message"); + logger.fatal("Fatal log message"); + logger.trace("Trace log message"); + } +} From d500209eeb0b2f7ad39be7ee7bbaade458db3cbd Mon Sep 17 00:00:00 2001 From: ukhan1980 <82222767+ukhan1980@users.noreply.github.com> Date: Thu, 1 Jul 2021 20:36:44 +0100 Subject: [PATCH 031/114] [BAEL-4264] Surefire and Failsafe comparison (#10968) * [BAEL-4264] Surefire and Failsafe comparison * [BAEL-4264] Update tests * [BAEL-4264] Move code to different module * [BAEL-4264] Rename test Co-authored-by: uzma khan --- maven-modules/maven-integration-test/pom.xml | 5 ++++- .../maven/it/FailsafeBuildPhaseIntegrationTest.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 maven-modules/maven-integration-test/src/integration-test/java/com/baeldung/maven/it/FailsafeBuildPhaseIntegrationTest.java diff --git a/maven-modules/maven-integration-test/pom.xml b/maven-modules/maven-integration-test/pom.xml index 4ab8de783d..692751366d 100644 --- a/maven-modules/maven-integration-test/pom.xml +++ b/maven-modules/maven-integration-test/pom.xml @@ -6,6 +6,7 @@ maven-integration-test 0.0.1-SNAPSHOT maven-integration-test + war com.baeldung @@ -116,7 +117,9 @@ verify - + + **/*IntegrationTest + diff --git a/maven-modules/maven-integration-test/src/integration-test/java/com/baeldung/maven/it/FailsafeBuildPhaseIntegrationTest.java b/maven-modules/maven-integration-test/src/integration-test/java/com/baeldung/maven/it/FailsafeBuildPhaseIntegrationTest.java new file mode 100644 index 0000000000..a50fa16394 --- /dev/null +++ b/maven-modules/maven-integration-test/src/integration-test/java/com/baeldung/maven/it/FailsafeBuildPhaseIntegrationTest.java @@ -0,0 +1,13 @@ +package com.baeldung.maven.it; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class FailsafeBuildPhaseIntegrationTest { + + @Test + public void whenTestExecutes_thenPreAndPostIntegrationBuildPhasesAreExecuted() { + assertTrue(true); + } +} From 8cea77cf581dbb0cb0b22c4454bad5def085855e Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:23:38 +0800 Subject: [PATCH 032/114] Update README.md --- rabbitmq/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rabbitmq/README.md b/rabbitmq/README.md index 218b1a4b14..1420998f66 100644 --- a/rabbitmq/README.md +++ b/rabbitmq/README.md @@ -4,4 +4,5 @@ This module contains articles about RabbitMQ. ### Relevant articles - [Introduction to RabbitMQ](https://www.baeldung.com/rabbitmq) +- [Exchanges, Queues, and Bindings in RabbitMQ](https://www.baeldung.com/java-rabbitmq-exchanges-queues-bindings) From 7df7443e685aa72bdb648bf7756cf8c8bd567288 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:29:15 +0800 Subject: [PATCH 033/114] Update README.md --- core-java-modules/core-java-concurrency-basic-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-concurrency-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md index c4a6105c56..d2ff75ca95 100644 --- a/core-java-modules/core-java-concurrency-basic-2/README.md +++ b/core-java-modules/core-java-concurrency-basic-2/README.md @@ -13,4 +13,5 @@ This module contains articles about basic Java concurrency - [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe) - [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time) - [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception) +- [How to Get the Number of Threads in a Java Process](https://www.baeldung.com/java-get-number-of-threads) - [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) From 1aba5c12a793dfd933a2c4aeeaa2a96125226ff7 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:30:22 +0800 Subject: [PATCH 034/114] Update README.md --- core-java-modules/core-java-lang-operators-2/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-java-modules/core-java-lang-operators-2/README.md b/core-java-modules/core-java-lang-operators-2/README.md index 46c874f361..1a4c01c6e5 100644 --- a/core-java-modules/core-java-lang-operators-2/README.md +++ b/core-java-modules/core-java-lang-operators-2/README.md @@ -3,3 +3,5 @@ This module contains articles about Java operators ## Relevant Articles: + +- [Logical vs Bitwise OR Operator](https://www.baeldung.com/java-logical-vs-bitwise-or-operator) From 3cca2f8716f5670889d3f3b25d51a6a521eb8ba4 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:32:00 +0800 Subject: [PATCH 035/114] Update README.md --- testing-modules/selenium-junit-testng/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/selenium-junit-testng/README.md b/testing-modules/selenium-junit-testng/README.md index aa3f0e8005..6ae5e9c9ef 100644 --- a/testing-modules/selenium-junit-testng/README.md +++ b/testing-modules/selenium-junit-testng/README.md @@ -5,3 +5,4 @@ - [Using Cookies With Selenium WebDriver in Java](https://www.baeldung.com/java-selenium-webdriver-cookies) - [Clicking Elements in Selenium using JavaScript](https://www.baeldung.com/java-selenium-javascript) - [Taking Screenshots With Selenium WebDriver](https://www.baeldung.com/java-selenium-screenshots) +- [Running Selenium Scripts with JMeter](https://www.baeldung.com/selenium-jmeter) From dcf850a45fd57871f3d2f0be3d67fd40ffd92e26 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:33:10 +0800 Subject: [PATCH 036/114] Update README.md --- spring-kafka/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-kafka/README.md b/spring-kafka/README.md index ddb086c3bd..588adc5b2c 100644 --- a/spring-kafka/README.md +++ b/spring-kafka/README.md @@ -6,6 +6,7 @@ This module contains articles about Spring with Kafka - [Intro to Apache Kafka with Spring](https://www.baeldung.com/spring-kafka) - [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing) +- [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag) ### Intro From dfa8224dfe5f406ab77895a4d4007ef18e0a8be4 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:34:38 +0800 Subject: [PATCH 037/114] Update README.md --- core-java-modules/core-java-lang-oop-constructors/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-lang-oop-constructors/README.md b/core-java-modules/core-java-lang-oop-constructors/README.md index 0082969807..4bec8db256 100644 --- a/core-java-modules/core-java-lang-oop-constructors/README.md +++ b/core-java-modules/core-java-lang-oop-constructors/README.md @@ -5,4 +5,5 @@ This module contains article about constructors in Java ### Relevant Articles: - [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors) - [Java Copy Constructor](https://www.baeldung.com/java-copy-constructor) -- [Cannot Reference “X†Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error) \ No newline at end of file +- [Cannot Reference “X†Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error) +- [Private Constructors in Java](https://www.baeldung.com/java-private-constructors) From 817c2a6e84cdd3ccd782ce7b8fe62d5d9d5f2cdb Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:36:03 +0800 Subject: [PATCH 038/114] Update README.md --- core-java-modules/core-java-security-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md index 684f2504cc..680a7de925 100644 --- a/core-java-modules/core-java-security-2/README.md +++ b/core-java-modules/core-java-security-2/README.md @@ -17,4 +17,5 @@ This module contains articles about core Java Security - [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception) - [The java.security.egd JVM Option](https://www.baeldung.com/java-security-egd) - [RSA in Java](https://www.baeldung.com/java-rsa) +- [3DES in Java](https://www.baeldung.com/java-3des) - More articles: [[<-- prev]](/core-java-modules/core-java-security) From f7f0a761abcee375858b5d6deb2b0c522cc051c7 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:37:35 +0800 Subject: [PATCH 039/114] Create README.md --- spring-native/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 spring-native/README.md diff --git a/spring-native/README.md b/spring-native/README.md new file mode 100644 index 0000000000..0f193252d0 --- /dev/null +++ b/spring-native/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Introduction to Spring Native](https://www.baeldung.com/spring-native-intro) From 07f6efa261bc1c8b930c061195ae3009ee84bf03 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:39:01 +0800 Subject: [PATCH 040/114] Update README.md --- core-java-modules/core-java-collections-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-4/README.md b/core-java-modules/core-java-collections-4/README.md index 4fd77473d4..0e14f407c4 100644 --- a/core-java-modules/core-java-collections-4/README.md +++ b/core-java-modules/core-java-collections-4/README.md @@ -6,3 +6,4 @@ - [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap) - [Java Deque vs. Stack](https://www.baeldung.com/java-deque-vs-stack) +- [Collection.toArray(new T[0]) or .toArray(new T[size])](https://www.baeldung.com/java-collection-toarray-methods) From 0a7e167bdf07a69fc6a061539673782402614e1e Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:40:28 +0800 Subject: [PATCH 041/114] Update README.md --- core-java-modules/core-java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md index 14857d5d87..f1cf2d8c09 100644 --- a/core-java-modules/core-java/README.md +++ b/core-java-modules/core-java/README.md @@ -12,3 +12,4 @@ - [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) - [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) - [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities) +- [Generating Alphanumeric UUID String in Java](https://www.baeldung.com/java-generate-alphanumeric-uuid) From 8c345dc7c8bf9d5d0745f01117011e8b6d7e16d4 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:41:29 +0800 Subject: [PATCH 042/114] Update README.md --- httpclient-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/httpclient-2/README.md b/httpclient-2/README.md index 9d7a9683cd..7c2d5862bd 100644 --- a/httpclient-2/README.md +++ b/httpclient-2/README.md @@ -11,4 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/apache-httpclient-tls) - [Reading an HTTP Response Body as a String in Java](https://www.baeldung.com/java-http-response-body-as-string) - [How To Get Cookies From the Apache HttpClient Response](https://www.baeldung.com/java-apache-httpclient-cookies) +- [Enabling Logging for Apache HttpClient](https://www.baeldung.com/java-httpclient-enable-logging) - More articles: [[<-- prev]](../httpclient) From d4a715e78c752076e76a68cdd7e2e8cea441981e Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 2 Jul 2021 05:45:00 +0800 Subject: [PATCH 043/114] Update README.md --- core-java-modules/core-java-regex-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-regex-2/README.md b/core-java-modules/core-java-regex-2/README.md index 7920ac456d..a73c8c4e89 100644 --- a/core-java-modules/core-java-regex-2/README.md +++ b/core-java-modules/core-java-regex-2/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Non-Capturing Regex Groups in Java](https://www.baeldung.com/java-regex-non-capturing-groups) +- [Lookahead and Lookbehind in Java Regex](https://www.baeldung.com/java-regex-lookahead-lookbehind) From fda111a5a14504cee7a653b32bb34d8989272aa1 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Fri, 2 Jul 2021 17:48:53 +0200 Subject: [PATCH 044/114] JAVA-6222: Fix issues in the spring-boot-cassandre (#10988) * JAVA-6222: Use parent-boot-2 in spring-boot-cassandre * JAVA-6222: Fix PMD violation * JAVA-6222: Cleanup pom.xml * JAVA-6222: Fix app and package names * JAVA-6222: Rename unit test to live test Co-authored-by: Krzysztof Woyke --- .../spring-boot-cassandre/pom.xml | 58 +++++++------------ .../trading}/MyFirstStrategy.java | 2 +- .../trading/TradingBotApplication.java} | 6 +- .../trading/MyFirstStrategyLiveTest.java} | 6 +- .../example/demo/DemoApplicationTests.java | 13 ----- 5 files changed, 28 insertions(+), 57 deletions(-) rename spring-boot-modules/spring-boot-cassandre/src/main/java/com/{example/demo => baeldung/trading}/MyFirstStrategy.java (98%) rename spring-boot-modules/spring-boot-cassandre/src/main/java/com/{example/demo/DemoApplication.java => baeldung/trading/TradingBotApplication.java} (60%) rename spring-boot-modules/spring-boot-cassandre/src/test/java/com/{example/demo/MyFirstStrategyUnitTest.java => baeldung/trading/MyFirstStrategyLiveTest.java} (94%) delete mode 100644 spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/DemoApplicationTests.java diff --git a/spring-boot-modules/spring-boot-cassandre/pom.xml b/spring-boot-modules/spring-boot-cassandre/pom.xml index 75163d2c2b..c4672c8887 100644 --- a/spring-boot-modules/spring-boot-cassandre/pom.xml +++ b/spring-boot-modules/spring-boot-cassandre/pom.xml @@ -3,66 +3,50 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.4.5 - - - com.example - demo - 0.0.1-SNAPSHOT - Cassandre trading bot tutorial + spring-boot-cassandre + jar + spring-boot-cassandre Cassandre trading bot tutorial - - 11 - - - - org.springframework.boot - spring-boot-starter - + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + tech.cassandre.trading.bot cassandre-trading-bot-spring-boot-starter - 4.2.1 + ${cassandre.trading.bot.version} org.knowm.xchange xchange-kucoin - 5.0.7 + ${xchange-kucoin.version} org.hsqldb hsqldb - 2.5.1 + ${hsqldb.version} - - org.springframework.boot - spring-boot-starter-test - test - - tech.cassandre.trading.bot cassandre-trading-bot-spring-boot-starter-test - 4.2.1 + ${cassandre.trading.bot.version} test - - - - org.springframework.boot - spring-boot-maven-plugin - 2.4.5 - - - + + 11 + 4.2.1 + 5.0.7 + 2.5.1 + diff --git a/spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/MyFirstStrategy.java b/spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/MyFirstStrategy.java similarity index 98% rename from spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/MyFirstStrategy.java rename to spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/MyFirstStrategy.java index ea8ae74aa6..92ef379a66 100644 --- a/spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/MyFirstStrategy.java +++ b/spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/MyFirstStrategy.java @@ -1,4 +1,4 @@ -package com.example.demo; +package com.baeldung.trading; import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.CLOSED; import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.OPENED; diff --git a/spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/DemoApplication.java b/spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/TradingBotApplication.java similarity index 60% rename from spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/DemoApplication.java rename to spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/TradingBotApplication.java index 094d95b93f..021c6c1d3b 100644 --- a/spring-boot-modules/spring-boot-cassandre/src/main/java/com/example/demo/DemoApplication.java +++ b/spring-boot-modules/spring-boot-cassandre/src/main/java/com/baeldung/trading/TradingBotApplication.java @@ -1,13 +1,13 @@ -package com.example.demo; +package com.baeldung.trading; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class DemoApplication { +public class TradingBotApplication { public static void main(String[] args) { - SpringApplication.run(DemoApplication.class, args); + SpringApplication.run(TradingBotApplication.class, args); } } diff --git a/spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/MyFirstStrategyUnitTest.java b/spring-boot-modules/spring-boot-cassandre/src/test/java/com/baeldung/trading/MyFirstStrategyLiveTest.java similarity index 94% rename from spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/MyFirstStrategyUnitTest.java rename to spring-boot-modules/spring-boot-cassandre/src/test/java/com/baeldung/trading/MyFirstStrategyLiveTest.java index bf7c353821..74986df971 100644 --- a/spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/MyFirstStrategyUnitTest.java +++ b/spring-boot-modules/spring-boot-cassandre/src/test/java/com/baeldung/trading/MyFirstStrategyLiveTest.java @@ -1,4 +1,4 @@ -package com.example.demo; +package com.baeldung.trading; import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -22,9 +22,9 @@ import tech.cassandre.trading.bot.test.mock.TickerFluxMock; @SpringBootTest @Import(TickerFluxMock.class) @DisplayName("Simple strategy test") -public class MyFirstStrategyUnitTest { +public class MyFirstStrategyLiveTest { - private final Logger logger = LoggerFactory.getLogger(MyFirstStrategyUnitTest.class); + private final Logger logger = LoggerFactory.getLogger(MyFirstStrategyLiveTest.class); @Autowired private MyFirstStrategy strategy; diff --git a/spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/DemoApplicationTests.java b/spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/DemoApplicationTests.java deleted file mode 100644 index eaa99696e2..0000000000 --- a/spring-boot-modules/spring-boot-cassandre/src/test/java/com/example/demo/DemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DemoApplicationTests { - - @Test - void contextLoads() { - } - -} From c31d5fffe1267101042891dab0582cb7deb65043 Mon Sep 17 00:00:00 2001 From: Mladen Savic Date: Sat, 3 Jul 2021 03:47:54 +0200 Subject: [PATCH 045/114] JPA Entities and the Serializable Interface (#10971) * JPA Entities and the Serializable Interface * JPA Entities and the Serializable Interface - edit after review * JPA Entities and the Serializable Interface - formatting * JPA Entities and the Serializable Interface - indentation --- .../hibernate/serializable/Account.java | 41 ++++++++++ .../hibernate/serializable/Email.java | 38 +++++++++ .../baeldung/hibernate/serializable/User.java | 36 +++++++++ .../hibernate/serializable/UserId.java | 27 +++++++ .../main/resources/META-INF/persistence.xml | 19 +++++ .../JPASerializableIntegrationTest.java | 77 +++++++++++++++++++ 6 files changed, 238 insertions(+) create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Account.java create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Email.java create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/User.java create mode 100644 persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/UserId.java create mode 100644 persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/serializable/JPASerializableIntegrationTest.java diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Account.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Account.java new file mode 100644 index 0000000000..b051809ee5 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Account.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.serializable; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Account { + + @Id + private long id; + private String type; + @ManyToOne + @JoinColumn(referencedColumnName = "email") + private User user; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } +} diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Email.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Email.java new file mode 100644 index 0000000000..11e7c6f159 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/Email.java @@ -0,0 +1,38 @@ +package com.baeldung.hibernate.serializable; + +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; + +@Entity +public class Email implements Serializable { + + @Id + private long id; + private String name; + private String domain; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } +} diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/User.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/User.java new file mode 100644 index 0000000000..e7820fe52f --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/User.java @@ -0,0 +1,36 @@ +package com.baeldung.hibernate.serializable; + +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +@Entity +public class User { + + @EmbeddedId private UserId userId; + private Email email; + + + public User() { + } + + public User(UserId userId, Email email) { + this.userId = userId; + this.email = email; + } + + public UserId getUserId() { + return userId; + } + + public void setUserId(UserId userId) { + this.userId = userId; + } + + public Email getEmail() { + return email; + } + + public void setEmail(Email email) { + this.email = email; + } +} diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/UserId.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/UserId.java new file mode 100644 index 0000000000..7d3d382f67 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/serializable/UserId.java @@ -0,0 +1,27 @@ +package com.baeldung.hibernate.serializable; + +import javax.persistence.Embeddable; +import java.io.Serializable; + +@Embeddable +public class UserId implements Serializable { + + private String name; + private String lastName; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml index c2d5bf59ab..3482414b9d 100644 --- a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml @@ -100,4 +100,23 @@ + + + EntityManager serializable persistence unit + com.baeldung.hibernate.serializable.Email + com.baeldung.hibernate.serializable.Account + com.baeldung.hibernate.serializable.User + com.baeldung.hibernate.serializable.UserId + true + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/serializable/JPASerializableIntegrationTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/serializable/JPASerializableIntegrationTest.java new file mode 100644 index 0000000000..696bc23ab0 --- /dev/null +++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/serializable/JPASerializableIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.hibernate.serializable; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.io.IOException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class JPASerializableIntegrationTest { + + private static EntityManager entityManager; + + @Before + public void setUp() throws IOException { + EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("com.baeldung.hibernate.serializable.h2_persistence_unit"); + entityManager = entityManagerFactory.createEntityManager(); + entityManager.getTransaction().begin(); + } + + @Test + public void givenUser_whenPersisted_thenUserWillBeFoundById() { + UserId userId = new UserId(); + userId.setName("John"); + userId.setLastName("Doe"); + Email email = new Email(); + email.setId(1); + email.setName("johndoe"); + email.setDomain("gmail.com"); + User user = new User(userId, email); + + entityManager.persist(user); + + User userDb = entityManager.find(User.class, userId); + assertEquals("johndoe", userDb.getEmail().getName()); + } + + @Test + public void givenAssociation_whenPersisted_thenMultipleAccountsWillBeFoundByEmail() { + UserId userId = new UserId(); + userId.setName("John"); + userId.setLastName("Doe"); + Email email = new Email(); + email.setId(1); + email.setName("johndoe"); + email.setDomain("gmail.com"); + User user = new User(userId, email); + Account account = new Account(); + account.setType("test"); + account.setId(10); + account.setUser(user); + Account account2 = new Account(); + account2.setType("main"); + account2.setId(11); + account2.setUser(user); + + entityManager.persist(user); + entityManager.persist(account); + entityManager.persist(account2); + + List userAccounts = entityManager.createQuery("select a from Account a join fetch a.user where a.user.email = :email") + .setParameter("email", email) + .getResultList(); + assertEquals(2, userAccounts.size()); + } + + @After + public void tearDown() { + entityManager.close(); + } + +} From 9930b4c945b1e3f68f0d4507dd1d85ad5821b100 Mon Sep 17 00:00:00 2001 From: kaushal Date: Sat, 3 Jul 2021 18:41:51 +0530 Subject: [PATCH 046/114] BAEL-4905: Send large messages with Kafka (#10992) --- .../kafka/KafkaApplicationLongMessage.java | 75 +++++++++++++++++++ .../spring/kafka/KafkaConsumerConfig.java | 7 ++ .../spring/kafka/KafkaProducerConfig.java | 2 + .../spring/kafka/KafkaTopicConfig.java | 12 +++ .../src/main/resources/application.properties | 1 + 5 files changed, 97 insertions(+) create mode 100644 spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplicationLongMessage.java diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplicationLongMessage.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplicationLongMessage.java new file mode 100644 index 0000000000..0af0a4b091 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplicationLongMessage.java @@ -0,0 +1,75 @@ +package com.baeldung.spring.kafka; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +@SpringBootApplication +public class KafkaApplicationLongMessage { + + public static void main(String[] args) throws Exception { + + ConfigurableApplicationContext context = SpringApplication.run(KafkaApplicationLongMessage.class, args); + + LongMessageProducer producer = context.getBean(LongMessageProducer.class); + + String fileData = readLongMessage(); + producer.sendMessage(fileData); + + //Deliberate delay to let listener consume produced message before main thread stops + Thread.sleep(5000); + context.close(); + } + + private static String readLongMessage() throws IOException { + String data = ""; + + //update complete location of large message here + data = new String(Files.readAllBytes(Paths.get("RandomTextFile.txt"))); + return data; + } + + @Bean + public LongMessageProducer longMessageProducer() { + return new LongMessageProducer(); + } + + @Bean + public LongMessageListener longMessageListener() { + return new LongMessageListener(); + } + + public static class LongMessageProducer { + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Value(value = "${long.message.topic.name}") + private String topicName; + + public void sendMessage(String message) { + kafkaTemplate.send(topicName, message); + System.out.println("Long message Sent"); + } + + } + + public static class LongMessageListener { + + @KafkaListener(topics = "${long.message.topic.name}", groupId = "longMessage", containerFactory = "longMessageKafkaListenerContainerFactory") + public void listenGroupLongMessage(String message) { + System.out.println("Received Message in group 'longMessage'"); + } + + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java index abaa431eec..9495fcf508 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java @@ -27,6 +27,8 @@ public class KafkaConsumerConfig { props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, "20971520"); + props.put(ConsumerConfig.FETCH_MAX_BYTES_CONFIG, "20971520"); return new DefaultKafkaConsumerFactory<>(props); } @@ -56,6 +58,11 @@ public class KafkaConsumerConfig { return kafkaListenerContainerFactory("partitions"); } + @Bean + public ConcurrentKafkaListenerContainerFactory longMessageKafkaListenerContainerFactory() { + return kafkaListenerContainerFactory("longMessage"); + } + @Bean public ConcurrentKafkaListenerContainerFactory filterKafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory factory = kafkaListenerContainerFactory("filter"); diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java index 0223bab0fe..9dff81a09d 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java @@ -25,6 +25,8 @@ public class KafkaProducerConfig { configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + configProps.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG, "20971520"); + return new DefaultKafkaProducerFactory<>(configProps); } diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java index 00e4147cd0..8a006a72bc 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java @@ -19,6 +19,9 @@ public class KafkaTopicConfig { @Value(value = "${message.topic.name}") private String topicName; + @Value(value = "${long.message.topic.name}") + private String longMsgTopicName; + @Value(value = "${partitioned.topic.name}") private String partitionedTopicName; @@ -54,4 +57,13 @@ public class KafkaTopicConfig { public NewTopic topic4() { return new NewTopic(greetingTopicName, 1, (short) 1); } + + @Bean + public NewTopic topic5() { + NewTopic newTopic = new NewTopic(longMsgTopicName, 1, (short) 1); + Map configs = new HashMap<>(); + configs.put("max.message.bytes", "20971520"); + newTopic.configs(configs); + return newTopic; + } } diff --git a/spring-kafka/src/main/resources/application.properties b/spring-kafka/src/main/resources/application.properties index e6a4668da3..e1a983339b 100644 --- a/spring-kafka/src/main/resources/application.properties +++ b/spring-kafka/src/main/resources/application.properties @@ -1,5 +1,6 @@ kafka.bootstrapAddress=localhost:9092 message.topic.name=baeldung +long.message.topic.name=longMessage greeting.topic.name=greeting filtered.topic.name=filtered partitioned.topic.name=partitioned From d1d9ada490866aa040e10ba7224458e7af244935 Mon Sep 17 00:00:00 2001 From: ashleyfrieze Date: Sat, 3 Jul 2021 17:43:55 +0100 Subject: [PATCH 047/114] BAEL-5025 Example code for camel case to words (#10964) --- .../camelcasetowords/CamelCaseToWords.java | 27 ++++++++++++ .../regex/camelcasetowords/Recapitalize.java | 43 +++++++++++++++++++ .../CamelCaseToWordsUnitTest.java | 39 +++++++++++++++++ .../RecapitalizeUnitTest.java | 35 +++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/CamelCaseToWords.java create mode 100644 core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/Recapitalize.java create mode 100644 core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/CamelCaseToWordsUnitTest.java create mode 100644 core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/RecapitalizeUnitTest.java diff --git a/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/CamelCaseToWords.java b/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/CamelCaseToWords.java new file mode 100644 index 0000000000..ea6593495f --- /dev/null +++ b/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/CamelCaseToWords.java @@ -0,0 +1,27 @@ +package com.baeldung.regex.camelcasetowords; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Convert a string in camelCase or TitleCase into a list of words + */ +public class CamelCaseToWords { + private static final Pattern WORD_FINDER = Pattern.compile("(([A-Z]?[a-z]+)|([A-Z]))"); + + /** + * Find the words in mixed case string like ThisIsText or HereIsSomeText + * @param text the text to parse + * @return the list of words to process + */ + public static List findWordsInMixedCase(String text) { + Matcher matcher = WORD_FINDER.matcher(text); + List words = new ArrayList<>(); + while (matcher.find()) { + words.add(matcher.group(0)); + } + return words; + } +} diff --git a/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/Recapitalize.java b/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/Recapitalize.java new file mode 100644 index 0000000000..f87e59c6cc --- /dev/null +++ b/core-java-modules/core-java-regex-2/src/main/java/com/baeldung/regex/camelcasetowords/Recapitalize.java @@ -0,0 +1,43 @@ +package com.baeldung.regex.camelcasetowords; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Recapitalize { + private static final Set STOP_WORDS = Stream.of("a", "an", "the", "and", + "but", "for", "at", "by", "to", "or") + .collect(Collectors.toSet()); + + public static String sentenceCase(List words) { + List capitalized = new ArrayList<>(); + for (int i = 0; i < words.size(); i++) { + String currentWord = words.get(i); + if (i == 0) { + capitalized.add(capitalizeFirst(currentWord)); + } else { + capitalized.add(currentWord.toLowerCase()); + } + } + return String.join(" ", capitalized) + "."; + } + + public static String capitalizeMyTitle(List words) { + List capitalized = new ArrayList<>(); + for (int i = 0; i < words.size(); i++) { + String currentWord = words.get(i); + if (i == 0 || !STOP_WORDS.contains(currentWord.toLowerCase())) { + capitalized.add(capitalizeFirst(currentWord)); + } else { + capitalized.add(currentWord.toLowerCase()); + } + } + return String.join(" ", capitalized); + } + + private static String capitalizeFirst(String word) { + return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(); + } +} diff --git a/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/CamelCaseToWordsUnitTest.java b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/CamelCaseToWordsUnitTest.java new file mode 100644 index 0000000000..a843945bba --- /dev/null +++ b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/CamelCaseToWordsUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.regex.camelcasetowords; + +import org.junit.jupiter.api.Test; + +import static com.baeldung.regex.camelcasetowords.CamelCaseToWords.findWordsInMixedCase; +import static org.assertj.core.api.Assertions.assertThat; + +class CamelCaseToWordsUnitTest { + + @Test + void givenPlainStringWithNonLetters_thenFindsWords() { + assertThat(findWordsInMixedCase("some words")) + .containsExactly("some", "words"); + } + + @Test + void givenWordsInCamelCase_thenFindsWords() { + assertThat(findWordsInMixedCase("thisIsCamelCaseText")) + .containsExactly("this", "Is", "Camel", "Case", "Text"); + } + + @Test + void givenWordsInTitleCase_thenFindsWords() { + assertThat(findWordsInMixedCase("ThisIsTitleCaseText")) + .containsExactly("This", "Is", "Title", "Case", "Text"); + } + + @Test + void givenWordsAcrossMultipleTexts_thenFindsWords() { + assertThat(findWordsInMixedCase("ThisIsTitleCaseText --- andSoIsThis")) + .containsExactly("This", "Is", "Title", "Case", "Text", "and", "So", "Is", "This"); + } + + @Test + void givenCamelCaseHasASingleLetterWord_thenItCanBeSplit() { + assertThat(findWordsInMixedCase("thisHasASingleLetterWord")) + .containsExactly("this", "Has", "A", "Single", "Letter", "Word"); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/RecapitalizeUnitTest.java b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/RecapitalizeUnitTest.java new file mode 100644 index 0000000000..32c8f39372 --- /dev/null +++ b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/camelcasetowords/RecapitalizeUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.regex.camelcasetowords; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static com.baeldung.regex.camelcasetowords.Recapitalize.*; +import static org.assertj.core.api.Assertions.assertThat; + +class RecapitalizeUnitTest { + + @Test + void givenWords_thenCanComposeSentence() { + assertThat(sentenceCase(Arrays.asList("these", "Words", "Form", "A", "Sentence"))) + .isEqualTo("These words form a sentence."); + } + + @Test + void givenNonStopWords_thenTitleIsComposed() { + assertThat(capitalizeMyTitle(Arrays.asList("title", "words", "capitalize"))) + .isEqualTo("Title Words Capitalize"); + } + + @Test + void givenStopWords_thenTitleHasThemInLowerCase() { + assertThat(capitalizeMyTitle(Arrays.asList("this", "is", "A", "title", "with", "a", "stop", "word", "or", "two"))) + .isEqualTo("This Is a Title With a Stop Word or Two"); + } + + @Test + void givenStopWordIsFirstWord_thenTitleHasItCapitalized() { + assertThat(capitalizeMyTitle(Arrays.asList("a", "stop", "word", "first"))) + .isEqualTo("A Stop Word First"); + } +} \ No newline at end of file From 8011badd120b6fbec0f70b7a3ba5d309d4893b07 Mon Sep 17 00:00:00 2001 From: Kai Yuan Date: Sat, 3 Jul 2021 18:51:44 +0200 Subject: [PATCH 048/114] 2 threads start at the same time (#10972) * 2 threads start at the same time * remove blank leading/trailing lines --- .../ThreadsStartAtSameTime.java | 59 +++++++++++++++++++ .../WorkerWithCountDownLatch.java | 24 ++++++++ .../WorkerWithCyclicBarrier.java | 25 ++++++++ 3 files changed, 108 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCountDownLatch.java create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCyclicBarrier.java diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java new file mode 100644 index 0000000000..72363aeb82 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java @@ -0,0 +1,59 @@ +package com.baeldung.threadsstartatsametime; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +public class ThreadsStartAtSameTime { + + public static void main(String[] args) throws BrokenBarrierException, InterruptedException { + usingCountDownLatch(); + + Thread.sleep(30); + + usingCyclicBarrier(); + } + + private static void usingCountDownLatch() throws InterruptedException { + System.out.println("==============================================="); + System.out.println(" >>> Using CountDownLatch <<<<"); + System.out.println("==============================================="); + + CountDownLatch latch = new CountDownLatch(1); + + WorkerWithCountDownLatch worker1 = new WorkerWithCountDownLatch("Worker with latch 1", latch); + WorkerWithCountDownLatch worker2 = new WorkerWithCountDownLatch("Worker with latch 2", latch); + + worker1.start(); + worker2.start(); + + Thread.sleep(10);//simulation of some actual work + + System.out.println("-----------------------------------------------"); + System.out.println(" Now release the latch:"); + System.out.println("-----------------------------------------------"); + latch.countDown(); + } + + private static void usingCyclicBarrier() throws BrokenBarrierException, InterruptedException { + System.out.println("\n==============================================="); + System.out.println(" >>> Using CyclicBarrier <<<<"); + System.out.println("==============================================="); + + CyclicBarrier barrier = new CyclicBarrier(3); + + WorkerWithCyclicBarrier worker1 = new WorkerWithCyclicBarrier("Worker with barrier 1", barrier); + WorkerWithCyclicBarrier worker2 = new WorkerWithCyclicBarrier("Worker with barrier 2", barrier); + + worker1.start(); + worker2.start(); + + Thread.sleep(10);//simulation of some actual work + + System.out.println("-----------------------------------------------"); + System.out.println(" Now open the barrier:"); + System.out.println("-----------------------------------------------"); + barrier.await(); + } + +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCountDownLatch.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCountDownLatch.java new file mode 100644 index 0000000000..44b95ec042 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCountDownLatch.java @@ -0,0 +1,24 @@ +package com.baeldung.threadsstartatsametime; + +import java.time.Instant; +import java.util.concurrent.CountDownLatch; + +public class WorkerWithCountDownLatch extends Thread { + private CountDownLatch latch; + + public WorkerWithCountDownLatch(String name, CountDownLatch latch) { + this.latch = latch; + setName(name); + } + + @Override public void run() { + try { + System.out.printf("[ %s ] created, blocked by the latch\n", getName()); + latch.await(); + System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now()); + // do actual work here... + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCyclicBarrier.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCyclicBarrier.java new file mode 100644 index 0000000000..99059e0725 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithCyclicBarrier.java @@ -0,0 +1,25 @@ +package com.baeldung.threadsstartatsametime; + +import java.time.Instant; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +public class WorkerWithCyclicBarrier extends Thread { + private CyclicBarrier barrier; + + public WorkerWithCyclicBarrier(String name, CyclicBarrier barrier) { + this.barrier = barrier; + this.setName(name); + } + + @Override public void run() { + try { + System.out.printf("[ %s ] created, blocked by the barrier\n", getName()); + barrier.await(); + System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now()); + // do actual work here... + } catch (InterruptedException | BrokenBarrierException e) { + e.printStackTrace(); + } + } +} From daf3450533db7c8b7fdcfc5124c41daa402354cd Mon Sep 17 00:00:00 2001 From: MeenaGawande <45625809+MeenaGawande@users.noreply.github.com> Date: Sun, 4 Jul 2021 03:25:12 +0530 Subject: [PATCH 049/114] [BAEL-4268]Different Serialization Approaches for Java (#10928) * [BAEL-4268]Different Serialization Approaches for Java Code Changes * [BAEL-4268]Different Serialization Approaches for Java Code formatting changes * [BAEL-4268]Different Serialization Approaches for Java Added user proto file * [BAEL-4268]Different Serialization Approaches for Java updated pom.xml * [BAEL-4268]Different Serialization Approaches for Java Fixed indentation in pom.xml * [BAEL-4268]Different Serialization Approaches for Java Updated pom.xml * [BAEL-4268]Different Serialization Approaches for Java Fixed indentation in pom.xml Co-authored-by: MeenaGawande --- libraries-data-io/pom.xml | 45 ++ .../serialization/protocols/User.java | 32 + .../serialization/protocols/UserProtos.java | 636 ++++++++++++++++++ .../ApacheThriftSerializationUnitTest.java | 32 + .../GoogleProtocolBufferUnitTest.java | 27 + .../protocols/GsonSerializationUnitTest.java | 51 ++ .../JacksonSerializationUnitTest.java | 61 ++ .../JavaNativeSerializationUnitTest.java | 38 ++ .../protocols/YAMLSerializationUnitTest.java | 66 ++ .../test/resources/protocols/gson_user.json | 4 + .../resources/protocols/jackson_user.json | 1 + .../src/test/resources/protocols/user.proto | 11 + .../src/test/resources/protocols/user.txt | Bin 0 -> 106 bytes .../src/test/resources/protocols/usersproto | 1 + .../resources/protocols/yamlbeans_user.yaml | 13 + 15 files changed, 1018 insertions(+) create mode 100644 libraries-data-io/src/main/java/com/baeldung/serialization/protocols/User.java create mode 100644 libraries-data-io/src/main/java/com/baeldung/serialization/protocols/UserProtos.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/ApacheThriftSerializationUnitTest.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GoogleProtocolBufferUnitTest.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GsonSerializationUnitTest.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JacksonSerializationUnitTest.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JavaNativeSerializationUnitTest.java create mode 100644 libraries-data-io/src/test/java/com/baeldung/serialization/protocols/YAMLSerializationUnitTest.java create mode 100644 libraries-data-io/src/test/resources/protocols/gson_user.json create mode 100644 libraries-data-io/src/test/resources/protocols/jackson_user.json create mode 100644 libraries-data-io/src/test/resources/protocols/user.proto create mode 100644 libraries-data-io/src/test/resources/protocols/user.txt create mode 100644 libraries-data-io/src/test/resources/protocols/usersproto create mode 100644 libraries-data-io/src/test/resources/protocols/yamlbeans_user.yaml diff --git a/libraries-data-io/pom.xml b/libraries-data-io/pom.xml index 58bfde9aa0..1335ba54d1 100644 --- a/libraries-data-io/pom.xml +++ b/libraries-data-io/pom.xml @@ -55,6 +55,46 @@ docx4j ${docx4j.version} + + + com.google.code.gson + gson + ${gson.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + com.esotericsoftware.yamlbeans + yamlbeans + ${yamlbeans.version} + + + + org.apache.thrift + libthrift + ${apache-thrift.version} + + + + com.google.protobuf + protobuf-java + ${google-protobuf.version} + org.assertj assertj-core @@ -73,6 +113,11 @@ 3.9.0 3.3.5 2.1 + 2.8.7 + 2.12.3 + 1.15 + 0.14.2 + 3.17.3 \ No newline at end of file diff --git a/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/User.java b/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/User.java new file mode 100644 index 0000000000..27eadfb5f6 --- /dev/null +++ b/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/User.java @@ -0,0 +1,32 @@ +package com.baeldung.serialization.protocols; + +import java.io.Serializable; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } +} \ No newline at end of file diff --git a/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/UserProtos.java b/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/UserProtos.java new file mode 100644 index 0000000000..adefabb7e8 --- /dev/null +++ b/libraries-data-io/src/main/java/com/baeldung/serialization/protocols/UserProtos.java @@ -0,0 +1,636 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: user.proto + +package com.baeldung.serialization.protocols; + +public final class UserProtos { + private UserProtos() { + } + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); + } + + public interface UserOrBuilder extends + // @@protoc_insertion_point(interface_extends:protobuf.User) + com.google.protobuf.MessageOrBuilder { + + /** + * int32 id = 1; + * @return The id. + */ + int getId(); + + /** + * string name = 2; + * @return The name. + */ + java.lang.String getName(); + + /** + * string name = 2; + * @return The bytes for name. + */ + com.google.protobuf.ByteString getNameBytes(); + } + + /** + * Protobuf type {@code protobuf.User} + */ + public static final class User extends com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:protobuf.User) + UserOrBuilder { + private static final long serialVersionUID = 0L; + + // Use User.newBuilder() to construct. + private User(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private User() { + name_ = ""; + } + + @java.lang.Override + @SuppressWarnings({ "unused" }) + protected java.lang.Object newInstance(UnusedPrivateParameter unused) { + return new User(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private User(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + id_ = input.readInt32(); + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + name_ = s; + break; + } + default: { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.serialization.protocols.UserProtos.internal_static_protobuf_User_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.serialization.protocols.UserProtos.internal_static_protobuf_User_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.serialization.protocols.UserProtos.User.class, + com.baeldung.serialization.protocols.UserProtos.User.Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + private int id_; + + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + + public static final int NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object name_; + + /** + * string name = 2; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + + /** + * string name = 2; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) + return true; + if (isInitialized == 0) + return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (id_ != 0) { + output.writeInt32(1, id_); + } + if (!getNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) + return size; + + size = 0; + if (id_ != 0) { + size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, id_); + } + if (!getNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.baeldung.serialization.protocols.UserProtos.User)) { + return super.equals(obj); + } + com.baeldung.serialization.protocols.UserProtos.User other = (com.baeldung.serialization.protocols.UserProtos.User) obj; + + if (getId() != other.getId()) + return false; + if (!getName().equals(other.getName())) + return false; + if (!unknownFields.equals(other.unknownFields)) + return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseDelimitedFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.baeldung.serialization.protocols.UserProtos.User parseFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.baeldung.serialization.protocols.UserProtos.User prototype) { + return DEFAULT_INSTANCE.toBuilder() + .mergeFrom(prototype); + } + + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code protobuf.User} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:protobuf.User) + com.baeldung.serialization.protocols.UserProtos.UserOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.serialization.protocols.UserProtos.internal_static_protobuf_User_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.serialization.protocols.UserProtos.internal_static_protobuf_User_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.serialization.protocols.UserProtos.User.class, + com.baeldung.serialization.protocols.UserProtos.User.Builder.class); + } + + // Construct using com.baeldung.serialization.compare.UserProtos.User.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { + } + } + + @java.lang.Override + public Builder clear() { + super.clear(); + id_ = 0; + + name_ = ""; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.baeldung.serialization.protocols.UserProtos.internal_static_protobuf_User_descriptor; + } + + @java.lang.Override + public com.baeldung.serialization.protocols.UserProtos.User getDefaultInstanceForType() { + return com.baeldung.serialization.protocols.UserProtos.User.getDefaultInstance(); + } + + @java.lang.Override + public com.baeldung.serialization.protocols.UserProtos.User build() { + com.baeldung.serialization.protocols.UserProtos.User result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.baeldung.serialization.protocols.UserProtos.User buildPartial() { + com.baeldung.serialization.protocols.UserProtos.User result = new com.baeldung.serialization.protocols.UserProtos.User(this); + result.id_ = id_; + result.name_ = name_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + + @java.lang.Override + public Builder setField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.setField(field, value); + } + + @java.lang.Override + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @java.lang.Override + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @java.lang.Override + public Builder setRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + + @java.lang.Override + public Builder addRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.addRepeatedField(field, value); + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.baeldung.serialization.protocols.UserProtos.User) { + return mergeFrom((com.baeldung.serialization.protocols.UserProtos.User) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.baeldung.serialization.protocols.UserProtos.User other) { + if (other == com.baeldung.serialization.protocols.UserProtos.User.getDefaultInstance()) + return this; + if (other.getId() != 0) { + setId(other.getId()); + } + if (!other.getName() + .isEmpty()) { + name_ = other.name_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + com.baeldung.serialization.protocols.UserProtos.User parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.baeldung.serialization.protocols.UserProtos.User) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int id_; + + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + + /** + * int32 id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId(int value) { + + id_ = value; + onChanged(); + return this; + } + + /** + * int32 id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + + id_ = 0; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + + /** + * string name = 2; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * string name = 2; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string name = 2; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + name_ = value; + onChanged(); + return this; + } + + /** + * string name = 2; + * @return This builder for chaining. + */ + public Builder clearName() { + + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + + /** + * string name = 2; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + name_ = value; + onChanged(); + return this; + } + + @java.lang.Override + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + // @@protoc_insertion_point(builder_scope:protobuf.User) + } + + // @@protoc_insertion_point(class_scope:protobuf.User) + private static final com.baeldung.serialization.protocols.UserProtos.User DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.baeldung.serialization.protocols.UserProtos.User(); + } + + public static com.baeldung.serialization.protocols.UserProtos.User getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public User parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return new User(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.baeldung.serialization.protocols.UserProtos.User getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + } + + private static final com.google.protobuf.Descriptors.Descriptor internal_static_protobuf_User_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_protobuf_User_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + return descriptor; + } + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { + java.lang.String[] descriptorData = { "\n\nuser.proto\022\010protobuf\" \n\004User\022\n\n\002id\030\001 \001" + "(\005\022\014\n\004name\030\002 \001(\tB0\n\"com.baeldung.seriali" + "zation.compareB\nUserProtosb\006proto3" }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}); + internal_static_protobuf_User_descriptor = getDescriptor().getMessageTypes() + .get(0); + internal_static_protobuf_User_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(internal_static_protobuf_User_descriptor, new java.lang.String[] { "Id", "Name", }); + } + // @@protoc_insertion_point(outer_class_scope) +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/ApacheThriftSerializationUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/ApacheThriftSerializationUnitTest.java new file mode 100644 index 0000000000..7b6aa0a24b --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/ApacheThriftSerializationUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; + +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TMemoryBuffer; +import org.junit.jupiter.api.Test; + +public class ApacheThriftSerializationUnitTest { + + @Test + public void whenUsingThriftForSerialization_ThenDataIsSameAfterDeserialization() throws TException { + + User user = new User(); + user.setId(2); + user.setName("Greg"); + + TMemoryBuffer trans = new TMemoryBuffer(4096); + TProtocol proto = new TBinaryProtocol(trans); + + proto.writeI32(user.getId()); + proto.writeString(user.getName()); + + int userId = proto.readI32(); + String userName = proto.readString(); + + assertEquals(2, userId); + assertEquals("Greg", userName); + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GoogleProtocolBufferUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GoogleProtocolBufferUnitTest.java new file mode 100644 index 0000000000..46d66049d4 --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GoogleProtocolBufferUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +public class GoogleProtocolBufferUnitTest { + + @Test + public void whenUsingProtocolBuffersSerialization_ThenObjectIsTheSameAfterDeserialization() throws IOException { + + String filePath = "src/test/resources/protocols/usersproto"; + + UserProtos.User user = UserProtos.User.newBuilder().setId(1234).setName("John Doe").build(); + FileOutputStream fos = new FileOutputStream(filePath); + user.writeTo(fos); + + UserProtos.User deserializedUser = UserProtos.User.newBuilder().mergeFrom(new FileInputStream(filePath)).build(); + + assertEquals(1234, deserializedUser.getId()); + assertEquals("John Doe", deserializedUser.getName()); + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GsonSerializationUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GsonSerializationUnitTest.java new file mode 100644 index 0000000000..513dcf6ce0 --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/GsonSerializationUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonSerializationUnitTest { + + @Test + public void whenSerializedUsingGson_ThenObjectIsSameAfterDeserialization() { + + User user = new User(); + user.setId(1); + user.setName("Mark"); + + String filePath = "src/test/resources/protocols/gson_user.json"; + + try (Writer writer = new FileWriter(filePath)) { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + gson.toJson(user, writer); + + assertTrue(Files.exists(Paths.get(filePath))); + + } catch (IOException e) { + e.printStackTrace(); + } + + try { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + User deserializedUser = gson.fromJson(new FileReader(filePath), User.class); + + assertEquals(1, deserializedUser.getId()); + assertEquals("Mark", deserializedUser.getName()); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JacksonSerializationUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JacksonSerializationUnitTest.java new file mode 100644 index 0000000000..4bfb88b290 --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JacksonSerializationUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JacksonSerializationUnitTest { + + @Test + public void whenUsingJacksonAPIForJSONSerialization_thenDeserializeCorrectObject() throws IOException { + + User user = new User(); + user.setId(1); + user.setName("Mark Jonson"); + + String filePath = "src/test/resources/protocols/jackson_user.json"; + + File file = new File(filePath); + + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(file, user); + + User deserializedUser = mapper.readValue(new File(filePath), User.class); + + assertEquals(1, deserializedUser.getId()); + assertEquals("Mark Jonson", deserializedUser.getName()); + } + + public static List populateListOfUsers() { + User user1 = new User(); + user1.setId(1); + user1.setName("Mark Jonson"); + + User user2 = new User(); + user2.setId(2); + user2.setName("Johny Beth"); + + User user3 = new User(); + user3.setId(3); + user3.setName("Eliza Green"); + + User user4 = new User(); + user4.setId(4); + user4.setName("Monica Doe"); + + List users = new ArrayList<>(); + users.add(user1); + users.add(user2); + users.add(user3); + users.add(user4); + + return users; + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JavaNativeSerializationUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JavaNativeSerializationUnitTest.java new file mode 100644 index 0000000000..bb4cc0df0e --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/JavaNativeSerializationUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.jupiter.api.Test; + +public class JavaNativeSerializationUnitTest { + + @Test + public void whenUsingJavaNativeSerialization_ThenObjectIsTheSameAfterDeserialization() throws IOException, ClassNotFoundException { + + User user = new User(); + user.setId(1); + user.setName("Mark"); + + String filePath = "src/test/resources/protocols/user.txt"; + + FileOutputStream fileOutputStream = new FileOutputStream(filePath); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(user); + objectOutputStream.flush(); + objectOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(filePath); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + User deserializedUser = (User) objectInputStream.readObject(); + objectInputStream.close(); + + assertEquals(1, deserializedUser.getId()); + assertEquals("Mark", deserializedUser.getName()); + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/YAMLSerializationUnitTest.java b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/YAMLSerializationUnitTest.java new file mode 100644 index 0000000000..7ef3f88511 --- /dev/null +++ b/libraries-data-io/src/test/java/com/baeldung/serialization/protocols/YAMLSerializationUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.serialization.protocols; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import com.esotericsoftware.yamlbeans.YamlReader; +import com.esotericsoftware.yamlbeans.YamlWriter; + +public class YAMLSerializationUnitTest { + + @Test + public void whenUsingYAMLBeansForSerialization_thenDeserializeCorrectMap() throws IOException { + + String filePath = "src/test/resources/protocols/yamlbeans_user.yaml"; + + YamlWriter writer = new YamlWriter(new FileWriter(filePath)); + writer.write(populateUserMap()); + writer.close(); + + YamlReader reader = new YamlReader(new FileReader(filePath)); + Object object = reader.read(); + reader.close(); + + assertTrue(object instanceof Map); + Map deserializedUsers = (Map) object; + + assertEquals(4, deserializedUsers.size()); + assertEquals("Mark Jonson", (deserializedUsers.get("User1").getName())); + assertEquals(1, (deserializedUsers.get("User1").getId())); + } + + private Map populateUserMap() { + + User user1 = new User(); + user1.setId(1); + user1.setName("Mark Jonson"); + + User user2 = new User(); + user2.setId(2); + user2.setName("Johny Beth"); + + User user3 = new User(); + user3.setId(3); + user3.setName("Eliza Green"); + + User user4 = new User(); + user4.setId(4); + user4.setName("Monica Doe"); + + Map users = new LinkedHashMap<>(); + users.put("User1", user1); + users.put("User2", user2); + users.put("User3", user3); + users.put("User4", user4); + + return users; + } +} \ No newline at end of file diff --git a/libraries-data-io/src/test/resources/protocols/gson_user.json b/libraries-data-io/src/test/resources/protocols/gson_user.json new file mode 100644 index 0000000000..5440a774f7 --- /dev/null +++ b/libraries-data-io/src/test/resources/protocols/gson_user.json @@ -0,0 +1,4 @@ +{ + "id": 1, + "name": "Mark" +} \ No newline at end of file diff --git a/libraries-data-io/src/test/resources/protocols/jackson_user.json b/libraries-data-io/src/test/resources/protocols/jackson_user.json new file mode 100644 index 0000000000..ce10cca7ea --- /dev/null +++ b/libraries-data-io/src/test/resources/protocols/jackson_user.json @@ -0,0 +1 @@ +{"id":1,"name":"Mark Jonson"} \ No newline at end of file diff --git a/libraries-data-io/src/test/resources/protocols/user.proto b/libraries-data-io/src/test/resources/protocols/user.proto new file mode 100644 index 0000000000..d4a231d6ec --- /dev/null +++ b/libraries-data-io/src/test/resources/protocols/user.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package protobuf; + +option java_package = "com.baeldung.serialization.protocols"; +option java_outer_classname = "UserProtos"; + +message User { + int32 id = 1; + string name = 2; + } \ No newline at end of file diff --git a/libraries-data-io/src/test/resources/protocols/user.txt b/libraries-data-io/src/test/resources/protocols/user.txt new file mode 100644 index 0000000000000000000000000000000000000000..c9f53bfd49e6ce4b268d58ae1a99b2d17e6b6aee GIT binary patch literal 106 zcmZ4UmVvdnh(R+sKUXg)F*PTpG%sDRIJGDDCnmK*fwD3@pBhMcDv0 CpCAYT literal 0 HcmV?d00001 diff --git a/libraries-data-io/src/test/resources/protocols/usersproto b/libraries-data-io/src/test/resources/protocols/usersproto new file mode 100644 index 0000000000..83dd650be6 --- /dev/null +++ b/libraries-data-io/src/test/resources/protocols/usersproto @@ -0,0 +1 @@ +Ò John Doe \ No newline at end of file diff --git a/libraries-data-io/src/test/resources/protocols/yamlbeans_user.yaml b/libraries-data-io/src/test/resources/protocols/yamlbeans_user.yaml new file mode 100644 index 0000000000..83726897b9 --- /dev/null +++ b/libraries-data-io/src/test/resources/protocols/yamlbeans_user.yaml @@ -0,0 +1,13 @@ +!java.util.LinkedHashMap +User1: !com.baeldung.serialization.protocols.User + id: 1 + name: Mark Jonson +User2: !com.baeldung.serialization.protocols.User + id: 2 + name: Johny Beth +User3: !com.baeldung.serialization.protocols.User + id: 3 + name: Eliza Green +User4: !com.baeldung.serialization.protocols.User + id: 4 + name: Monica Doe From 1e5af80428073e6eb5a41f53dffc4b9a9833dd0d Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sat, 3 Jul 2021 17:09:09 -0500 Subject: [PATCH 050/114] BAEL-4993: add link back to article (#10994) --- persistence-modules/hibernate-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate-jpa/README.md b/persistence-modules/hibernate-jpa/README.md index 64ec9dcae3..8379ad1626 100644 --- a/persistence-modules/hibernate-jpa/README.md +++ b/persistence-modules/hibernate-jpa/README.md @@ -13,3 +13,4 @@ This module contains articles specific to use of Hibernate as a JPA implementati - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) - [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) +- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable) From 2e6ba6c3a13a30a703a20c561eed4450275e0789 Mon Sep 17 00:00:00 2001 From: devanshtrivedi5 Date: Mon, 5 Jul 2021 04:21:55 +0530 Subject: [PATCH 051/114] Grouping by collector java (#10986) * Initial Commit - Ports and Adapters * Restructured code to implement input and outbou ports and adapters * Added tests for groupingBy Collector * Revert "Initial Commit - Ports and Adapters" This reverts commit 55152dea * Added tests for groupingBy Collector * reverting * corrected typo * used BDD naming strategy for tests * Added a test for groupingByConcurrent * added new module and package * added core-java-streams-4 module in main pom.xml * updated pom.xml and changed artifactId --- .../core-java-streams-4/.gitignore | 26 +++++ .../core-java-streams-4/README.md | 6 ++ core-java-modules/core-java-streams-4/pom.xml | 63 ++++++++++++ .../StreamGroupingByCollectorUnitTest.java | 99 +++++++++++++++++++ .../src/test/resources/.gitignore | 13 +++ core-java-modules/pom.xml | 1 + 6 files changed, 208 insertions(+) create mode 100644 core-java-modules/core-java-streams-4/.gitignore create mode 100644 core-java-modules/core-java-streams-4/README.md create mode 100644 core-java-modules/core-java-streams-4/pom.xml create mode 100644 core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java create mode 100644 core-java-modules/core-java-streams-4/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-streams-4/.gitignore b/core-java-modules/core-java-streams-4/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/core-java-modules/core-java-streams-4/.gitignore @@ -0,0 +1,26 @@ +*.class + +0.* + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* +.resourceCache + +# Packaged files # +*.jar +*.war +*.ear + +# Files generated by integration tests +*.txt +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml \ No newline at end of file diff --git a/core-java-modules/core-java-streams-4/README.md b/core-java-modules/core-java-streams-4/README.md new file mode 100644 index 0000000000..06b426d8a7 --- /dev/null +++ b/core-java-modules/core-java-streams-4/README.md @@ -0,0 +1,6 @@ +## Core Java streams + +This module contains articles about the Stream API in Java. + +### Relevant Articles: +- [Count Occurrences using Java groupingBy Collector](https://baeldung.com/count-occurrences-with-java-groupingby-collector) diff --git a/core-java-modules/core-java-streams-4/pom.xml b/core-java-modules/core-java-streams-4/pom.xml new file mode 100644 index 0000000000..0a411bcc43 --- /dev/null +++ b/core-java-modules/core-java-streams-4/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + core-java-streams-4 + 0.1.0-SNAPSHOT + core-java-streams + jar + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + log4j + log4j + ${log4j.version} + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + + + core-java-streams-4 + + + src/main + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + -parameters + + + + + + + + 3.1 + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java new file mode 100644 index 0000000000..74b9d61370 --- /dev/null +++ b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java @@ -0,0 +1,99 @@ +package com.baeldung.streamcollectors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.junit.Assert; +import org.junit.Test; + +public class StreamGroupingByCollectorUnitTest +{ + static class Employee { + + Integer employeeId; + String employeeName; + Integer departmentId; + + Employee(Integer employeeId, String employeeName, Integer departmentId) { + this.employeeId = employeeId; + this.employeeName = employeeName; + this.departmentId = departmentId; + } + + public Integer getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(Integer employeeId) { + this.employeeId = employeeId; + } + + public String getEmployeeName() { + return employeeName; + } + + public void setEmployeeName(String employeeName) { + this.employeeName = employeeName; + } + + public Integer getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Integer departmentId) { + this.departmentId = departmentId; + } + } + + @Test + public void + givenListOfStrings_whenGroupingEqualStrings_thenUseCollectorsGroupingByToGroupEqualStringsAndCountOfOccurrences() { + List list = new ArrayList<>( + Arrays.asList("Foo", "Bar", "Bar", "Foo", "Bar") + ); + + Map result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + Assert.assertEquals(new Long(2), result.get("Foo")); + Assert.assertEquals(new Long(3), result.get("Bar")); + + } + + @Test + public void + givenListOfStrings_whenGroupingEqualLengthStrings_thenUseCollectorsGroupingByConcurrentToGroupEqualLengthStringsAndCountOfOccurrences() { + + List list = new ArrayList<>( + Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian") + ); + + Map result = list.stream() + .collect(Collectors.groupingByConcurrent(String::length, Collectors.counting())); + Assert.assertEquals(new Long(2), result.get(3)); + Assert.assertEquals(new Long(3), result.get(4)); + + } + + + @Test + public void + givenListOfEmployees_whenGroupingDepartmentId_thenUseCollectorsGroupingByDepartmentIdAndCountNumberOfEmployeesWithinEveryDepartment() { + + List list = new ArrayList<>( + Arrays.asList(new Employee(1, "Joe", 1), + new Employee(2, "Josh", 1), + new Employee(3, "Jamie", 2), + new Employee(4, "Jim", 2), + new Employee(5, "Jack", 2)) + ); + + Map result = list.stream() .collect(Collectors.groupingBy(Employee::getDepartmentId, Collectors.counting())); + Assert.assertEquals(new Long(2), result.get(1)); + Assert.assertEquals(new Long(3), result.get(2)); + + } + +} diff --git a/core-java-modules/core-java-streams-4/src/test/resources/.gitignore b/core-java-modules/core-java-streams-4/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-modules/core-java-streams-4/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 8661f1ba01..8c6df97ad7 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -103,6 +103,7 @@ core-java-streams core-java-streams-2 core-java-streams-3 + core-java-streams-4 core-java-string-algorithms core-java-string-algorithms-2 core-java-string-algorithms-3 From 95faea30bb8937dfbe0ef29d6abd66396851c468 Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Tue, 6 Jul 2021 12:18:59 +0200 Subject: [PATCH 052/114] JAVA-6091: Fix enum comparison --- .../baeldung/libraries/debezium/service/CustomerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries-data-db/src/main/java/com/baeldung/libraries/debezium/service/CustomerService.java b/libraries-data-db/src/main/java/com/baeldung/libraries/debezium/service/CustomerService.java index 4b35a94eb5..cce8b78808 100644 --- a/libraries-data-db/src/main/java/com/baeldung/libraries/debezium/service/CustomerService.java +++ b/libraries-data-db/src/main/java/com/baeldung/libraries/debezium/service/CustomerService.java @@ -21,7 +21,7 @@ public class CustomerService { final ObjectMapper mapper = new ObjectMapper(); final Customer customer = mapper.convertValue(customerData, Customer.class); - if (Operation.DELETE.name().equals(operation.name())) { + if (Operation.DELETE == operation) { customerRepository.deleteById(customer.getId()); } else { customerRepository.save(customer); From dee85d33c13f7c1d63b51aedd1e7c2338468fd62 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Tue, 6 Jul 2021 16:54:57 +0200 Subject: [PATCH 053/114] BAEL-5015: Add Java 9 example for readAllBytes (#10999) Co-authored-by: Krzysztof Woyke --- core-java-modules/core-java-io-conversions-2/pom.xml | 12 ++++++++++++ .../JavaInputStreamToXUnitTest.java | 10 ++++++++++ core-java-modules/pom.xml | 1 - pom.xml | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-io-conversions-2/pom.xml b/core-java-modules/core-java-io-conversions-2/pom.xml index e594666b55..dcb9d494dc 100644 --- a/core-java-modules/core-java-io-conversions-2/pom.xml +++ b/core-java-modules/core-java-io-conversions-2/pom.xml @@ -36,6 +36,16 @@ core-java-io-conversions-2 + + + org.apache.maven.plugins + maven-compiler-plugin + + ${source.version} + ${target.version} + + + src/main/resources @@ -45,6 +55,8 @@ + 11 + 11 20200518 4.1 diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java index c34c32891f..dbce18ee5e 100644 --- a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java +++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java @@ -70,6 +70,16 @@ public class JavaInputStreamToXUnitTest { assertThat(text, equalTo(originalString)); } + @Test + public void givenUsingJava9_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + final String text = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + + assertThat(text, equalTo(originalString)); + } + @Test public final void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { final String originalString = randomAlphabetic(DEFAULT_SIZE); diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 8c6df97ad7..9f2ebb1d35 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -63,7 +63,6 @@ core-java-io-4 core-java-io-apis core-java-io-conversions - core-java-io-conversions-2 core-java-jar core-java-jndi core-java-jvm diff --git a/pom.xml b/pom.xml index 477ae66454..830bcf33fa 100644 --- a/pom.xml +++ b/pom.xml @@ -1292,6 +1292,7 @@ core-java-modules/core-java-date-operations-1 core-java-modules/core-java-datetime-conversion core-java-modules/core-java-datetime-string + core-java-modules/core-java-io-conversions-2 core-java-modules/core-java-jpms core-java-modules/core-java-os core-java-modules/core-java-string-operations-3 @@ -1338,6 +1339,7 @@ core-java-modules/core-java-date-operations-1 core-java-modules/core-java-datetime-conversion core-java-modules/core-java-datetime-string + core-java-modules/core-java-io-conversions-2 core-java-modules/core-java-jpms core-java-modules/core-java-os core-java-modules/core-java-string-operations-3 From bd4beba1f0224dff3238b96cd69e5dcdd10cb71d Mon Sep 17 00:00:00 2001 From: devanshtrivedi5 Date: Wed, 7 Jul 2021 11:00:22 +0530 Subject: [PATCH 054/114] Grouping by collector java (#11001) * Initial Commit - Ports and Adapters * Restructured code to implement input and outbou ports and adapters * Added tests for groupingBy Collector * Revert "Initial Commit - Ports and Adapters" This reverts commit 55152dea * Added tests for groupingBy Collector * reverting * corrected typo * used BDD naming strategy for tests * Added a test for groupingByConcurrent * added new module and package * added core-java-streams-4 module in main pom.xml * updated pom.xml and changed artifactId * removed gitignore and README.md Converted spaces to tabs and reformatted code * removed gitignore and README.md * used baeldung formatter --- .../core-java-streams-4/README.md | 6 - .../StreamGroupingByCollectorUnitTest.java | 125 ++++++++---------- .../src/test/resources/.gitignore | 13 -- 3 files changed, 55 insertions(+), 89 deletions(-) delete mode 100644 core-java-modules/core-java-streams-4/README.md delete mode 100644 core-java-modules/core-java-streams-4/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-streams-4/README.md b/core-java-modules/core-java-streams-4/README.md deleted file mode 100644 index 06b426d8a7..0000000000 --- a/core-java-modules/core-java-streams-4/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Java streams - -This module contains articles about the Stream API in Java. - -### Relevant Articles: -- [Count Occurrences using Java groupingBy Collector](https://baeldung.com/count-occurrences-with-java-groupingby-collector) diff --git a/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java index 74b9d61370..c50d73a638 100644 --- a/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java +++ b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java @@ -10,90 +10,75 @@ import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Test; -public class StreamGroupingByCollectorUnitTest -{ - static class Employee { +public class StreamGroupingByCollectorUnitTest { + @Test + public void givenListOfStrings_whenGroupingEqualStrings_thenUseCollectorsGroupingByToGroupEqualStringsAndCountOfOccurrences() { - Integer employeeId; - String employeeName; - Integer departmentId; + List list = new ArrayList<>(Arrays.asList("Foo", "Bar", "Bar", "Foo", "Bar")); - Employee(Integer employeeId, String employeeName, Integer departmentId) { - this.employeeId = employeeId; - this.employeeName = employeeName; - this.departmentId = departmentId; - } + Map result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + Assert.assertEquals(new Long(2), result.get("Foo")); + Assert.assertEquals(new Long(3), result.get("Bar")); - public Integer getEmployeeId() { - return employeeId; - } + } - public void setEmployeeId(Integer employeeId) { - this.employeeId = employeeId; - } + @Test + public void givenListOfStrings_whenGroupingEqualLengthStrings_thenUseCollectorsGroupingByConcurrentToGroupEqualLengthStringsAndCountOfOccurrences() { - public String getEmployeeName() { - return employeeName; - } + List list = new ArrayList<>(Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian")); - public void setEmployeeName(String employeeName) { - this.employeeName = employeeName; - } + Map result = list.stream().collect(Collectors.groupingByConcurrent(String::length, Collectors.counting())); + Assert.assertEquals(new Long(2), result.get(3)); + Assert.assertEquals(new Long(3), result.get(4)); - public Integer getDepartmentId() { - return departmentId; - } + } - public void setDepartmentId(Integer departmentId) { - this.departmentId = departmentId; - } + @Test + public void givenListOfEmployees_whenGroupingDepartmentId_thenUseCollectorsGroupingByDepartmentIdAndCountNumberOfEmployeesWithinEveryDepartment() { + + List list = new ArrayList<>(Arrays.asList(new Employee(1, "Joe", 1), new Employee(2, "Josh", 1), new Employee(3, "Jamie", 2), new Employee(4, "Jim", 2), new Employee(5, "Jack", 2))); + + Map result = list.stream().collect(Collectors.groupingBy(Employee::getDepartmentId, Collectors.counting())); + Assert.assertEquals(new Long(2), result.get(1)); + Assert.assertEquals(new Long(3), result.get(2)); + + } + + static class Employee { + + Integer employeeId; + String employeeName; + Integer departmentId; + + Employee(Integer employeeId, String employeeName, Integer departmentId) { + this.employeeId = employeeId; + this.employeeName = employeeName; + this.departmentId = departmentId; } - @Test - public void - givenListOfStrings_whenGroupingEqualStrings_thenUseCollectorsGroupingByToGroupEqualStringsAndCountOfOccurrences() { - List list = new ArrayList<>( - Arrays.asList("Foo", "Bar", "Bar", "Foo", "Bar") - ); - - Map result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - Assert.assertEquals(new Long(2), result.get("Foo")); - Assert.assertEquals(new Long(3), result.get("Bar")); - + public Integer getEmployeeId() { + return employeeId; } - @Test - public void - givenListOfStrings_whenGroupingEqualLengthStrings_thenUseCollectorsGroupingByConcurrentToGroupEqualLengthStringsAndCountOfOccurrences() { - - List list = new ArrayList<>( - Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian") - ); - - Map result = list.stream() - .collect(Collectors.groupingByConcurrent(String::length, Collectors.counting())); - Assert.assertEquals(new Long(2), result.get(3)); - Assert.assertEquals(new Long(3), result.get(4)); - + public void setEmployeeId(Integer employeeId) { + this.employeeId = employeeId; } - - @Test - public void - givenListOfEmployees_whenGroupingDepartmentId_thenUseCollectorsGroupingByDepartmentIdAndCountNumberOfEmployeesWithinEveryDepartment() { - - List list = new ArrayList<>( - Arrays.asList(new Employee(1, "Joe", 1), - new Employee(2, "Josh", 1), - new Employee(3, "Jamie", 2), - new Employee(4, "Jim", 2), - new Employee(5, "Jack", 2)) - ); - - Map result = list.stream() .collect(Collectors.groupingBy(Employee::getDepartmentId, Collectors.counting())); - Assert.assertEquals(new Long(2), result.get(1)); - Assert.assertEquals(new Long(3), result.get(2)); - + public String getEmployeeName() { + return employeeName; } + public void setEmployeeName(String employeeName) { + this.employeeName = employeeName; + } + + public Integer getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Integer departmentId) { + this.departmentId = departmentId; + } + } + } diff --git a/core-java-modules/core-java-streams-4/src/test/resources/.gitignore b/core-java-modules/core-java-streams-4/src/test/resources/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/core-java-modules/core-java-streams-4/src/test/resources/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.class - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file From fe18b30a3410ffd907ba79490ecc4be0dd81cd10 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:09:06 +0800 Subject: [PATCH 055/114] Update README.md --- maven-modules/maven-integration-test/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maven-modules/maven-integration-test/README.md b/maven-modules/maven-integration-test/README.md index e73a73e61e..708cb3bf23 100644 --- a/maven-modules/maven-integration-test/README.md +++ b/maven-modules/maven-integration-test/README.md @@ -7,4 +7,5 @@ This module contains articles about Integration Testing with Maven and related p - [Integration Testing with Maven](https://www.baeldung.com/maven-integration-test) - [Build a Jar with Maven and Ignore the Test Results](https://www.baeldung.com/maven-ignore-test-results) - [Quick Guide to the Maven Surefire Plugin](https://www.baeldung.com/maven-surefire-plugin) -- [The Maven Failsafe Plugin](https://www.baeldung.com/maven-failsafe-plugin) \ No newline at end of file +- [The Maven Failsafe Plugin](https://www.baeldung.com/maven-failsafe-plugin) +- [Difference Between Maven Surefire and Failsafe Plugins](https://www.baeldung.com/maven-surefire-vs-failsafe) From 24a3e9b3515f26b843352e7b2a16a32335a2fa3f Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:17:34 +0800 Subject: [PATCH 056/114] Update README.md --- spring-boot-modules/spring-boot-swagger/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-boot-swagger/README.md b/spring-boot-modules/spring-boot-swagger/README.md index 1038031210..f94ae75c41 100644 --- a/spring-boot-modules/spring-boot-swagger/README.md +++ b/spring-boot-modules/spring-boot-swagger/README.md @@ -1,3 +1,4 @@ ## Relevant Articles: - [Hiding Endpoints From Swagger Documentation in Spring Boot](https://www.baeldung.com/spring-swagger-hiding-endpoints) +- [Swagger @Api Description Is Deprecated](https://www.baeldung.com/java-swagger-api-description-deprecated) From dc2ccf984f2950bfe9e7f2ba603fd1c11b5aede0 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:19:11 +0800 Subject: [PATCH 057/114] Update README.md --- spring-boot-modules/spring-boot-springdoc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-boot-springdoc/README.md b/spring-boot-modules/spring-boot-springdoc/README.md index 608e4afa2e..4ac4147da6 100644 --- a/spring-boot-modules/spring-boot-springdoc/README.md +++ b/spring-boot-modules/spring-boot-springdoc/README.md @@ -3,3 +3,4 @@ - [Documenting a Spring REST API Using OpenAPI 3.0](https://www.baeldung.com/spring-rest-openapi-documentation) - [Spring REST Docs vs OpenAPI](https://www.baeldung.com/spring-rest-docs-vs-openapi) - [Hiding Endpoints From Swagger Documentation in Spring Boot](https://www.baeldung.com/spring-swagger-hiding-endpoints) +- [Swagger @Api Description Is Deprecated](https://www.baeldung.com/java-swagger-api-description-deprecated) From a9e2931e50d3ecee77f63a240242ca9d866c533b Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:22:36 +0800 Subject: [PATCH 058/114] Update README.md --- libraries-data-io/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-data-io/README.md b/libraries-data-io/README.md index 3e68334ec9..16c7cc66eb 100644 --- a/libraries-data-io/README.md +++ b/libraries-data-io/README.md @@ -10,3 +10,4 @@ This module contains articles about IO data processing libraries. - [Interact with Google Sheets from Java](https://www.baeldung.com/google-sheets-java-client) - [Introduction To Docx4J](https://www.baeldung.com/docx4j) - [Breaking YAML Strings Over Multiple Lines](https://www.baeldung.com/yaml-multi-line) +- [Different Serialization Approaches for Java](https://www.baeldung.com/java-serialization-approaches) From 84d61f69f2c2a310e88589e2aaec47f4a525d30c Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:24:39 +0800 Subject: [PATCH 059/114] Update README.md --- core-java-modules/core-java-regex-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-regex-2/README.md b/core-java-modules/core-java-regex-2/README.md index a73c8c4e89..25656c3cb1 100644 --- a/core-java-modules/core-java-regex-2/README.md +++ b/core-java-modules/core-java-regex-2/README.md @@ -2,3 +2,4 @@ - [Non-Capturing Regex Groups in Java](https://www.baeldung.com/java-regex-non-capturing-groups) - [Lookahead and Lookbehind in Java Regex](https://www.baeldung.com/java-regex-lookahead-lookbehind) +- [Converting Camel Case and Title Case to Words in Java](https://www.baeldung.com/java-camel-case-title-case-to-words) From 1cd9efa35c3a532043b4def12feb4bd19af01fde Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:27:01 +0800 Subject: [PATCH 060/114] Update README.md --- core-java-modules/core-java-concurrency-advanced-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-concurrency-advanced-4/README.md b/core-java-modules/core-java-concurrency-advanced-4/README.md index 5b93cec0dd..db856a2cd6 100644 --- a/core-java-modules/core-java-concurrency-advanced-4/README.md +++ b/core-java-modules/core-java-concurrency-advanced-4/README.md @@ -2,3 +2,4 @@ - [Binary Semaphore vs Reentrant Lock](https://www.baeldung.com/java-binary-semaphore-vs-reentrant-lock) - [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices) +- [Start Two Threads at the Exact Same Time in Java](https://www.baeldung.com/java-start-two-threads-at-same-time) From 41e789eaefe620f2c4abf20b6ba0f5edafba7c51 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:29:24 +0800 Subject: [PATCH 061/114] Update README.md --- spring-kafka/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-kafka/README.md b/spring-kafka/README.md index 588adc5b2c..2b71beaac9 100644 --- a/spring-kafka/README.md +++ b/spring-kafka/README.md @@ -7,6 +7,7 @@ This module contains articles about Spring with Kafka - [Intro to Apache Kafka with Spring](https://www.baeldung.com/spring-kafka) - [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing) - [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag) +- [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message) ### Intro From f02fba02a0863b20602d34dd7490f2c158300691 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 7 Jul 2021 23:31:00 +0800 Subject: [PATCH 062/114] Update README.md --- testing-modules/junit-5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index 984b79c29d..5101f92928 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -8,3 +8,4 @@ - [Guide to Dynamic Tests in JUnit 5](https://www.baeldung.com/junit5-dynamic-tests) - [Determine the Execution Time of JUnit Tests](https://www.baeldung.com/junit-test-execution-time) - [@BeforeAll and @AfterAll in Non-Static Methods](https://www.baeldung.com/java-beforeall-afterall-non-static) +- [The java.lang.NoClassDefFoundError in JUnit](https://www.baeldung.com/junit-noclassdeffounderror) From 00df9206fe41f727c0d54f3374f6d983cfc86bb3 Mon Sep 17 00:00:00 2001 From: sgrverma23 Date: Fri, 9 Jul 2021 02:37:44 +0530 Subject: [PATCH 063/114] Extra source Directory in Maven by sgrverma23 (#10991) * Extra source Direcotry in Maven * Update pom.xml correcting Java version Co-authored-by: Sakshi Verma --- maven-modules/maven-builder-plugin/pom.xml | 41 +++++++++++++++++++ .../com/baeldung/maven/plugin/MainApp.java | 12 ++++++ .../com/baeldung/database/DataConnection.java | 7 ++++ maven-modules/pom.xml | 1 + 4 files changed, 61 insertions(+) create mode 100644 maven-modules/maven-builder-plugin/pom.xml create mode 100644 maven-modules/maven-builder-plugin/src/main/java/com/baeldung/maven/plugin/MainApp.java create mode 100644 maven-modules/maven-builder-plugin/src/main/newsrc/com/baeldung/database/DataConnection.java diff --git a/maven-modules/maven-builder-plugin/pom.xml b/maven-modules/maven-builder-plugin/pom.xml new file mode 100644 index 0000000000..0eaa858db7 --- /dev/null +++ b/maven-modules/maven-builder-plugin/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.example + maven-builder-plugin + 1.0-SNAPSHOT + + + 1.8 + 1.8 + UTF-8 + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + add-source + generate-sources + + add-source + + + + src/main/newsrc/ + + + + + + + + diff --git a/maven-modules/maven-builder-plugin/src/main/java/com/baeldung/maven/plugin/MainApp.java b/maven-modules/maven-builder-plugin/src/main/java/com/baeldung/maven/plugin/MainApp.java new file mode 100644 index 0000000000..176951e21a --- /dev/null +++ b/maven-modules/maven-builder-plugin/src/main/java/com/baeldung/maven/plugin/MainApp.java @@ -0,0 +1,12 @@ +package com.baeldung.maven.plugin; + +import com.baeldung.database.DataConnection; + +public class MainApp { + + public static void main(String args[]){ + + System.out.println(DataConnection.temp()); + + } +} diff --git a/maven-modules/maven-builder-plugin/src/main/newsrc/com/baeldung/database/DataConnection.java b/maven-modules/maven-builder-plugin/src/main/newsrc/com/baeldung/database/DataConnection.java new file mode 100644 index 0000000000..8ab05a5658 --- /dev/null +++ b/maven-modules/maven-builder-plugin/src/main/newsrc/com/baeldung/database/DataConnection.java @@ -0,0 +1,7 @@ +package com.baeldung.database; +public class DataConnection { + + public static String temp(){ + return "secondary source directory"; + } +} diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index 0f146e26da..7e8bf20553 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -32,6 +32,7 @@ version-overriding-plugins versions-maven-plugin maven-printing-plugins + maven-builder-plugin From 1910561a543134a59443a13a58600c98584130d2 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Fri, 9 Jul 2021 05:13:41 +0200 Subject: [PATCH 064/114] JAVA-5986: Cleanup pom.xml files (#11010) Co-authored-by: Krzysztof Woyke --- core-java-modules/pom.xml | 1 - pom.xml | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 9f2ebb1d35..f727695036 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -48,7 +48,6 @@ core-java-concurrency-collections core-java-concurrency-collections-2 core-java-console - core-java-8-datetime-2 core-java-date-operations-2 core-java-8-datetime diff --git a/pom.xml b/pom.xml index 830bcf33fa..acdb0a95fd 100644 --- a/pom.xml +++ b/pom.xml @@ -1284,10 +1284,12 @@ core-java-modules/core-java-9-streams core-java-modules/core-java-10 + core-java-modules/core-java-11 core-java-modules/core-java-11-2 + core-java-modules/core-java-collections-set core-java-modules/core-java-date-operations-1 core-java-modules/core-java-datetime-conversion @@ -1335,6 +1337,7 @@ + core-java-modules/core-java-collections-set core-java-modules/core-java-date-operations-1 core-java-modules/core-java-datetime-conversion From 37db34cb8acdd42834e5d9af0df42e61440fd6f5 Mon Sep 17 00:00:00 2001 From: anmoldeep0123 Date: Fri, 9 Jul 2021 14:57:55 +0530 Subject: [PATCH 065/114] BAEL-4933 | Differences between static classes and the singleton pattern in Java (#11014) * BAEL-4220 | A Guide to IllegalAccessError and when it happens * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | BDD test names * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4933 | Differences between static classes and the singleton pattern in Java Co-authored-by: root --- .../CachingSingleton.java | 30 ++++++++ .../FileSystemSingleton.java | 36 +++++++++ .../staticsingletondifference/MyLock.java | 8 ++ .../SerializableCloneableSingleton.java | 49 ++++++++++++ .../SingletonInterface.java | 10 +++ .../SingletonLock.java | 20 +++++ .../staticsingletondifference/SubUtility.java | 8 ++ .../SuperUtility.java | 8 ++ .../ForSingletonsUnitTest.java | 77 +++++++++++++++++++ 9 files changed, 246 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/CachingSingleton.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/FileSystemSingleton.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/MyLock.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SerializableCloneableSingleton.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonInterface.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonLock.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SubUtility.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SuperUtility.java create mode 100644 core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticsingletondifference/ForSingletonsUnitTest.java diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/CachingSingleton.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/CachingSingleton.java new file mode 100644 index 0000000000..d472e386eb --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/CachingSingleton.java @@ -0,0 +1,30 @@ +package com.baeldung.staticsingletondifference; + +public class CachingSingleton implements SingletonInterface { + + private CachingSingleton() { + } + + private static class SingletonHolder { + public static final CachingSingleton instance = new CachingSingleton(); + } + + public static CachingSingleton getInstance() { + return SingletonHolder.instance; + } + + @Override + public String describeMe() { + return "Caching Responsibilities"; + } + + @Override + public String passOnLocks(MyLock lock) { + return lock.takeLock(1); + } + + @Override + public void increment() { + throw new UnsupportedOperationException("Not Supported Here"); + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/FileSystemSingleton.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/FileSystemSingleton.java new file mode 100644 index 0000000000..84ea5d4d1a --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/FileSystemSingleton.java @@ -0,0 +1,36 @@ +package com.baeldung.staticsingletondifference; + +public class FileSystemSingleton implements SingletonInterface{ + + private int filesWritten; + + private FileSystemSingleton() { + } + + private static class SingletonHolder { + public static final FileSystemSingleton instance = new FileSystemSingleton(); + } + + public static FileSystemSingleton getInstance() { + return SingletonHolder.instance; + } + + @Override + public String describeMe() { + return "File System Responsibilities"; + } + + @Override + public String passOnLocks(MyLock lock) { + return lock.takeLock(2); + } + + @Override + public void increment() { + this.filesWritten++; + } + + public int getFilesWritten() { + return filesWritten; + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/MyLock.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/MyLock.java new file mode 100644 index 0000000000..3a124bd678 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/MyLock.java @@ -0,0 +1,8 @@ +package com.baeldung.staticsingletondifference; + +public class MyLock { + + protected String takeLock(int locks) { + return "Taken Specific Lock"; + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SerializableCloneableSingleton.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SerializableCloneableSingleton.java new file mode 100644 index 0000000000..64a422f9ec --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SerializableCloneableSingleton.java @@ -0,0 +1,49 @@ +package com.baeldung.staticsingletondifference; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +public class SerializableCloneableSingleton implements SingletonInterface, Serializable, Cloneable { + + private static final long serialVersionUID = -1917003064592196223L; + + private int state; + + private SerializableCloneableSingleton() { + } + + private static class SingletonHolder { + public static final SerializableCloneableSingleton instance = new SerializableCloneableSingleton(); + } + + public static SerializableCloneableSingleton getInstance() { + return SingletonHolder.instance; + } + + @Override + public String describeMe() { + throw new UnsupportedOperationException("Not Supported Here"); + } + + @Override + public String passOnLocks(MyLock lock) { + throw new UnsupportedOperationException("Not Supported Here"); + } + + @Override + public void increment() { + this.state++; + } + + public int getState() { + return state; + } + + private Object readResolve() throws ObjectStreamException { + return SingletonHolder.instance; + } + + public Object cloneObject() throws CloneNotSupportedException { + return this.clone(); + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonInterface.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonInterface.java new file mode 100644 index 0000000000..34e14c5cac --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonInterface.java @@ -0,0 +1,10 @@ +package com.baeldung.staticsingletondifference; + +public interface SingletonInterface { + + public String describeMe(); + + public String passOnLocks(MyLock lock); + + public void increment(); +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonLock.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonLock.java new file mode 100644 index 0000000000..35d9931597 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SingletonLock.java @@ -0,0 +1,20 @@ +package com.baeldung.staticsingletondifference; + +public class SingletonLock extends MyLock { + + private SingletonLock() { + } + + private static class SingletonHolder { + public static final SingletonLock instance = new SingletonLock(); + } + + public static SingletonLock getInstance() { + return SingletonHolder.instance; + } + + @Override + public String takeLock(int locks) { + return "Taken Singleton Lock"; + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SubUtility.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SubUtility.java new file mode 100644 index 0000000000..c9661cbf70 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SubUtility.java @@ -0,0 +1,8 @@ +package com.baeldung.staticsingletondifference; + +public class SubUtility extends SuperUtility { + + public static String echoIt(String data) { + return data; + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SuperUtility.java b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SuperUtility.java new file mode 100644 index 0000000000..00011f4697 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/main/java/com/baeldung/staticsingletondifference/SuperUtility.java @@ -0,0 +1,8 @@ +package com.baeldung.staticsingletondifference; + +public class SuperUtility { + + public static String echoIt(String data) { + return "SUPER"; + } +} diff --git a/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticsingletondifference/ForSingletonsUnitTest.java b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticsingletondifference/ForSingletonsUnitTest.java new file mode 100644 index 0000000000..4b0b23b5ec --- /dev/null +++ b/core-java-modules/core-java-lang-oop-modifiers/src/test/java/com/baeldung/staticsingletondifference/ForSingletonsUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.staticsingletondifference; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.stream.IntStream; + +import org.junit.Assert; +import org.junit.Test; + +public class ForSingletonsUnitTest { + + @Test + public void whenStaticUtilClassInheritance_thenOverridingFails() { + SuperUtility superUtility = new SubUtility(); + Assert.assertNotEquals("ECHO", superUtility.echoIt("ECHO")); + Assert.assertEquals("SUPER", superUtility.echoIt("ECHO")); + } + + @Test + public void whenSingletonDerivesBaseClass_thenRuntimePolymorphism() { + MyLock myLock = new MyLock(); + Assert.assertEquals("Taken Specific Lock", myLock.takeLock(10)); + myLock = SingletonLock.getInstance(); + Assert.assertEquals("Taken Singleton Lock", myLock.takeLock(10)); + } + + @Test + public void whenSingletonImplementsInterface_thenRuntimePolymorphism() { + SingletonInterface singleton = FileSystemSingleton.getInstance(); + Assert.assertEquals("File System Responsibilities", singleton.describeMe()); + singleton = CachingSingleton.getInstance(); + Assert.assertEquals("Caching Responsibilities", singleton.describeMe()); + } + + @Test + public void whenSingleton_thenPassAsArguments() { + SingletonInterface singleton = FileSystemSingleton.getInstance(); + Assert.assertEquals("Taken Singleton Lock", singleton.passOnLocks(SingletonLock.getInstance())); + } + + @Test + public void whenSingleton_thenAllowState() { + SingletonInterface singleton = FileSystemSingleton.getInstance(); + IntStream.range(0, 5) + .forEach(i -> singleton.increment()); + Assert.assertEquals(5, ((FileSystemSingleton) singleton).getFilesWritten()); + } + + @Test + public void whenSingleton_thenAllowSerializationDeserialization() { + SingletonInterface singleton = SerializableCloneableSingleton.getInstance(); + singleton.increment(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + new ObjectOutputStream(baos).writeObject(singleton); + SerializableCloneableSingleton singletonNew = (SerializableCloneableSingleton) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject(); + Assert.assertEquals(1, singletonNew.getState()); + Assert.assertEquals(singleton.hashCode(), singletonNew.hashCode()); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + @Test + public void whenSingleton_thenAllowCloneable() { + SerializableCloneableSingleton singleton = SerializableCloneableSingleton.getInstance(); + singleton.increment(); + try { + Assert.assertEquals(2, ((SerializableCloneableSingleton) singleton.cloneObject()).getState()); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file From 3ed0cfe585485235ba1c9a59590a28af0f9867c3 Mon Sep 17 00:00:00 2001 From: Mateusz Szablak Date: Fri, 9 Jul 2021 16:29:40 +0200 Subject: [PATCH 066/114] BAEL-4920 - How BigInteger works (#11016) Co-authored-by: Mateusz Szablak --- .../biginteger/BigIntegerUnitTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 java-numbers-4/src/test/java/com/baeldung/biginteger/BigIntegerUnitTest.java diff --git a/java-numbers-4/src/test/java/com/baeldung/biginteger/BigIntegerUnitTest.java b/java-numbers-4/src/test/java/com/baeldung/biginteger/BigIntegerUnitTest.java new file mode 100644 index 0000000000..4ac185984d --- /dev/null +++ b/java-numbers-4/src/test/java/com/baeldung/biginteger/BigIntegerUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.biginteger; + +import org.junit.jupiter.api.Test; + +import java.math.BigInteger; +import java.nio.ByteBuffer; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BigIntegerUnitTest { + + @Test + void givenPositiveAndNegativeAndZeroBigInteger_whenGetSigNumValue_shouldReturnOneAndMinusOneAndZero() { + assertEquals(1, BigInteger.TEN.signum()); + assertEquals(-1, BigInteger.TEN.negate().signum()); + assertEquals(0, BigInteger.ZERO.signum()); + } + + @Test + void givenByteArrays_whenCreateBigInteger_shouldTranslateToTwosComplementBinary() { + assertEquals(new BigInteger("1"), new BigInteger(new byte[]{0b1})); + assertEquals(new BigInteger("2"), new BigInteger(new byte[]{0b10})); + assertEquals(new BigInteger("4"), new BigInteger(new byte[]{0b100})); + } + + @Test + void givenSingleByte_whenCreateBigIntegerAndDifferentSigNum_thenOppositeValues() { + byte[] bytes = { (byte) -128 }; // 0b1000_0000 + + BigInteger positive = new BigInteger(1, bytes); + BigInteger negative = new BigInteger(-1, bytes); + + assertEquals(new BigInteger("128"), positive); + assertEquals("10000000", positive.toString(2)); + + assertEquals(new BigInteger("-128"), negative); + assertEquals("-10000000", negative.toString(2)); + } + + @Test + void givenZeroBigInteger_whenCheckMagnitude_thenIsEmpty() { + assertEquals(0, BigInteger.ZERO.bitCount()); + assertEquals(BigInteger.ZERO, new BigInteger(0, new byte[]{})); + } + + @Test + void given63rdBitSet_whenCreateBigInteger_thenIsLargerThanLongByOne() { + // first + BigInteger bi1 = BigInteger.ZERO.setBit(63); + String str1 = bi1.toString(2); + + // second + byte[] bytes = ByteBuffer.allocate(Long.BYTES).putLong(Long.MIN_VALUE).array(); + BigInteger bi2 = new BigInteger(1, bytes); + String str2 = bi2.toString(2); + + largerThanLongAssertionSet(bi1, str1); + + assertEquals(bi1, bi2); + + largerThanLongAssertionSet(bi2, str2); + + } + + private static void largerThanLongAssertionSet(BigInteger bi, String str) + { + assertEquals(64, bi.bitLength()); + assertEquals(1, bi.signum()); + assertEquals("9223372036854775808", bi.toString()); + assertEquals(BigInteger.ONE, bi.subtract(BigInteger.valueOf(Long.MAX_VALUE))); + + assertEquals(64, str.length()); + assertTrue(str.matches("^10{63}$")); // 1000 0000 + } +} From c343ce694a460e285af3558538b2129e60358f4a Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 27 Jun 2021 22:33:38 +0530 Subject: [PATCH 067/114] BAEL-3759: Guava's Futures and ListenableFuture * Added new module guava-modules/guava-concurrency * Added implementation code for simple usages of ListenableFuture * Added implementation code for complex usages of ListenableFuture --- guava-modules/guava-concurrency/pom.xml | 14 + .../guava/future/ListenableFutureService.java | 105 +++++++ .../exception/ListenableFutureException.java | 4 + .../ListenableFutureComplexUnitTest.java | 277 ++++++++++++++++++ .../ListenableFutureSimpleUnitTest.java | 122 ++++++++ guava-modules/pom.xml | 1 + 6 files changed, 523 insertions(+) create mode 100644 guava-modules/guava-concurrency/pom.xml create mode 100644 guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/ListenableFutureService.java create mode 100644 guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/exception/ListenableFutureException.java create mode 100644 guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureComplexUnitTest.java create mode 100644 guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureSimpleUnitTest.java diff --git a/guava-modules/guava-concurrency/pom.xml b/guava-modules/guava-concurrency/pom.xml new file mode 100644 index 0000000000..ef7f756596 --- /dev/null +++ b/guava-modules/guava-concurrency/pom.xml @@ -0,0 +1,14 @@ + + + + guava-modules + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + + guava-concurrency + + \ No newline at end of file diff --git a/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/ListenableFutureService.java b/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/ListenableFutureService.java new file mode 100644 index 0000000000..b6620bd1e2 --- /dev/null +++ b/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/ListenableFutureService.java @@ -0,0 +1,105 @@ +package com.baeldung.guava.future; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import com.baeldung.guava.future.exception.ListenableFutureException; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +public class ListenableFutureService { + + private final ListeningExecutorService lExecService; + + public ListenableFutureService() { + this.lExecService = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); + } + + public ListenableFutureService(ListeningExecutorService lExecService) { + this.lExecService = lExecService; + } + + public ListenableFuture fetchConfig(String configKey) { + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE)); + }); + } + + public FutureTask fetchConfigTask(String configKey) { + return new FutureTask<>(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE)); + }); + } + + public ListenableFutureTask fetchConfigListenableTask(String configKey) { + return ListenableFutureTask.create(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE)); + }); + } + + public ListenableFuture succeedingTask() { + return Futures.immediateFuture(new Random().nextInt(Integer.MAX_VALUE)); + } + + public ListenableFuture failingTask() { + return Futures.immediateFailedFuture(new ListenableFutureException()); + } + + public ListenableFuture getCartId() { + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return new Random().nextInt(Integer.MAX_VALUE); + }); + } + + public ListenableFuture getCustomerName() { + String[] names = new String[] { "Mark", "Jane", "June" }; + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return names[new Random().nextInt(names.length)]; + }); + } + + public ListenableFuture> getCartItems() { + String[] items = new String[] { "Apple", "Orange", "Mango", "Pineapple" }; + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + + int noOfItems = new Random().nextInt(items.length); + if (noOfItems == 0) ++noOfItems; + + return Arrays.stream(items, 0, noOfItems).collect(Collectors.toList()); + }); + } + + public ListenableFuture generateUsername(String firstName) { + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + return firstName.replaceAll("[^a-zA-Z]+","") + .concat("@service.com"); + }); + } + + public ListenableFuture generatePassword(String username) { + return lExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); + if (username.contains("@")) { + String[] parts = username.split("@"); + return parts[0] + "123@" + parts[1]; + } else { + return username + "123"; + } + }); + } +} \ No newline at end of file diff --git a/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/exception/ListenableFutureException.java b/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/exception/ListenableFutureException.java new file mode 100644 index 0000000000..921c02b54a --- /dev/null +++ b/guava-modules/guava-concurrency/src/main/java/com/baeldung/guava/future/exception/ListenableFutureException.java @@ -0,0 +1,4 @@ +package com.baeldung.guava.future.exception; + +public class ListenableFutureException extends Exception { +} diff --git a/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureComplexUnitTest.java b/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureComplexUnitTest.java new file mode 100644 index 0000000000..27a1cc6592 --- /dev/null +++ b/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureComplexUnitTest.java @@ -0,0 +1,277 @@ +package com.baeldung.guava.future; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.function.UnaryOperator; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.junit.jupiter.api.Test; + +import com.baeldung.guava.future.exception.ListenableFutureException; +import com.google.common.base.Function; +import com.google.common.util.concurrent.AsyncCallable; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +public class ListenableFutureComplexUnitTest { + + @Test + public void givenAllSucceedingTasks_whenAllAsList_thenAllSuccess() { + final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService(); + final ListenableFutureService service = new ListenableFutureService(listeningExecService); + + ListenableFuture task1 = service.fetchConfig("config.0"); + ListenableFuture task2 = service.fetchConfig("config.1"); + ListenableFuture task3 = service.fetchConfig("config.2"); + + ListenableFuture> configsTask = Futures.allAsList(task1, task2, task3); + Futures.addCallback(configsTask, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List configResults) { + assertNotNull(configResults); + assertEquals(3, configResults.size()); + for (int i = 0; i < 3; i++) { + assertTrue(configResults.get(i) + .contains("config." + i)); + } + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, listeningExecService); + } + + @Test + public void givenOneFailingTask_whenAllAsList_thenFailure() { + final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService(); + final ListenableFutureService service = new ListenableFutureService(listeningExecService); + + ListenableFuture task1 = service.fetchConfig("config.0"); + ListenableFuture task2 = service.failingTask(); + ListenableFuture task3 = service.fetchConfig("config.2"); + + ListenableFuture> configsTask = Futures.allAsList(task1, task2, task3); + Futures.addCallback(configsTask, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List configResults) { + fail("Expected a failed future"); + } + + @Override + public void onFailure(Throwable t) { + assertTrue(t instanceof ListenableFutureException); + } + }, listeningExecService); + } + + @Test + public void givenOneFailingTask_whenSuccessfulAsList_thenSomeSuccess() { + final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService(); + final ListenableFutureService service = new ListenableFutureService(listeningExecService); + + ListenableFuture task1 = service.fetchConfig("config.0"); + ListenableFuture task2 = service.failingTask(); + ListenableFuture task3 = service.fetchConfig("config.2"); + + ListenableFuture> configsTask = Futures.successfulAsList(task1, task2, task3); + + Futures.addCallback(configsTask, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List configResults) { + assertNotNull(configResults); + assertTrue(configResults.get(0).contains("config.0")); + assertNull(configResults.get(1)); + assertTrue(configResults.get(2).contains("config.2")); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, listeningExecService); + } + + @Test + public void givenAllSucceedingTasks_whenAllSucceed_thenSuccess() { + ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService(); + ListenableFutureService service = new ListenableFutureService(listeningExecService); + + ListenableFuture cartIdTask = service.getCartId(); + ListenableFuture customerNameTask = service.getCustomerName(); + ListenableFuture> cartItemsTask = service.getCartItems(); + + ListenableFuture cartInfoTask = Futures.whenAllSucceed(cartIdTask, customerNameTask, cartItemsTask) + .call(() -> { + int cartId = Futures.getDone(cartIdTask); + String customerName = Futures.getDone(customerNameTask); + List cartItems = Futures.getDone(cartItemsTask); + return new CartInfo(cartId, customerName, cartItems); + }, listeningExecService); + + Futures.addCallback(cartInfoTask, new FutureCallback() { + @Override + public void onSuccess(@Nullable CartInfo result) { + assertNotNull(result); + assertTrue(result.cartId >= 0); + assertFalse(result.customerName.isEmpty()); + assertFalse(result.cartItems.isEmpty()); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, listeningExecService); + } + + @Test + public void givenAllSucceedingTasks_whenAllComplete_thenSomeSuccess() { + ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService(); + ListenableFutureService service = new ListenableFutureService(listeningExecService); + + ListenableFuture cartIdTask = service.getCartId(); + ListenableFuture customerNameTask = service.failingTask(); + ListenableFuture> cartItemsTask = service.getCartItems(); + + ListenableFuture cartInfoTask = Futures.whenAllComplete(cartIdTask, customerNameTask, cartItemsTask) + .call(() -> { + Integer cartId = getOrNull(cartIdTask); + String customerName = getOrNull(customerNameTask); + List cartItems = getOrNull(cartItemsTask); + return new CartInfo(cartId, customerName, cartItems); + }, listeningExecService); + + Futures.addCallback(cartInfoTask, new FutureCallback() { + @Override + public void onSuccess(@Nullable CartInfo result) { + assertNotNull(result); + assertTrue(result.cartId >= 0); + assertNull(result.customerName); + assertFalse(result.cartItems.isEmpty()); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, listeningExecService); + } + + @Test + public void whenTransform_thenTransformSuccess() { + ListeningExecutorService listenExecService = MoreExecutors.newDirectExecutorService(); + ListenableFutureService service = new ListenableFutureService(listenExecService); + + ListenableFuture> cartItemsTask = service.getCartItems(); + + Function, Integer> itemCountFunc = cartItems -> { + assertNotNull(cartItems); + return cartItems.size(); + }; + + ListenableFuture itemCountTask = Futures.transform(cartItemsTask, itemCountFunc, listenExecService); + + Futures.addCallback(itemCountTask, new FutureCallback() { + @Override + public void onSuccess(@Nullable Integer cartItemCount) { + assertNotNull(cartItemCount); + assertTrue(cartItemCount > 0); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, listenExecService); + } + + @Test + public void whenSubmitAsync_thenSuccess() { + ListeningExecutorService executor = MoreExecutors.newDirectExecutorService(); + ListenableFutureService service = new ListenableFutureService(executor); + + AsyncCallable asyncConfigTask = () -> { + ListenableFuture configTask = service.fetchConfig("config.a"); + TimeUnit.MILLISECONDS.sleep(500); //some long running task + return configTask; + }; + + ListenableFuture configTask = Futures.submitAsync(asyncConfigTask, executor); + + Futures.addCallback(configTask, new FutureCallback() { + @Override + public void onSuccess(@Nullable String result) { + assertNotNull(result); + assertTrue(result.contains("config.a")); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, executor); + } + + @Test + public void whenAsyncTransform_thenSuccess() { + ListeningExecutorService executor = MoreExecutors.newDirectExecutorService(); + ListenableFutureService service = new ListenableFutureService(executor); + + ListenableFuture usernameTask = service.generateUsername("john"); + AsyncFunction passwordFunc = username -> { + ListenableFuture generatePasswordTask = service.generatePassword(username); + TimeUnit.MILLISECONDS.sleep(500); // some long running task + return generatePasswordTask; + }; + + ListenableFuture passwordTask = Futures.transformAsync(usernameTask, passwordFunc, executor); + + Futures.addCallback(passwordTask, new FutureCallback() { + @Override + public void onSuccess(@Nullable String password) { + assertNotNull(password); + assertTrue(password.contains("john")); + assertTrue(password.contains("@")); + } + + @Override + public void onFailure(Throwable t) { + fail("Unexpected failure detected", t); + } + }, executor); + } + + private static T getOrNull(ListenableFuture future) { + try { + return Futures.getDone(future); + } catch (ExecutionException e) { + return null; + } + } + + static class CartInfo { + Integer cartId; + String customerName; + List cartItems; + + public CartInfo(Integer cartId, String customerName, List cartItems) { + this.cartId = cartId; + this.customerName = customerName; + this.cartItems = cartItems; + } + } +} \ No newline at end of file diff --git a/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureSimpleUnitTest.java b/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureSimpleUnitTest.java new file mode 100644 index 0000000000..7dce11a33f --- /dev/null +++ b/guava-modules/guava-concurrency/src/test/java/com/baeldung/guava/future/ListenableFutureSimpleUnitTest.java @@ -0,0 +1,122 @@ +package com.baeldung.guava.future; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; + +import com.baeldung.guava.future.exception.ListenableFutureException; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +public class ListenableFutureSimpleUnitTest { + + @Test + public void whenSubmitToListeningExecutor_thenSuccess() throws ExecutionException, InterruptedException { + ExecutorService execService = Executors.newSingleThreadExecutor(); + ListeningExecutorService listeningExecService = MoreExecutors.listeningDecorator(execService); + + ListenableFuture asyncTask = listeningExecService.submit(() -> { + TimeUnit.MILLISECONDS.sleep(500); // long running task + return 5; + }); + + assertEquals(5, asyncTask.get()); + } + + @Test + public void + givenJavaExecutor_whenSubmitListeningTask_thenSuccess() throws ExecutionException, InterruptedException { + Executor executor = Executors.newSingleThreadExecutor(); + ListenableFutureService service = new ListenableFutureService(); + + FutureTask configFuture = service.fetchConfigTask("future.value"); + executor.execute(configFuture); + assertTrue(configFuture.get().contains("future.value")); + + ListenableFutureTask configListenableFuture = + service.fetchConfigListenableTask("listenable.value"); + executor.execute(configListenableFuture); + assertTrue(configListenableFuture.get().contains("listenable.value")); + } + + @Test + public void givenNonFailingTask_whenCallbackListen_thenSuccess() { + Executor listeningExecutor = MoreExecutors.directExecutor(); + + ListenableFuture succeedingTask = new ListenableFutureService().succeedingTask(); + Futures.addCallback(succeedingTask, new FutureCallback() { + @Override + public void onSuccess(Integer result) { + assertNotNull(result); + assertTrue(result >= 0); + } + + @Override + public void onFailure(Throwable t) { + fail("Succeeding task cannot failed", t); + } + }, listeningExecutor); + } + + @Test + public void givenFailingTask_whenCallbackListen_thenThrows() { + Executor listeningExecutor = MoreExecutors.directExecutor(); + + ListenableFuture failingTask = new ListenableFutureService().failingTask(); + Futures.addCallback(failingTask, new FutureCallback() { + @Override + public void onSuccess(Integer result) { + fail("Failing task cannot succeed"); + } + + @Override + public void onFailure(Throwable t) { + assertTrue(t instanceof ListenableFutureException); + } + }, listeningExecutor); + } + + @Test + public void givenNonFailingTask_whenDirectListen_thenListenerExecutes() { + Executor listeningExecutor = MoreExecutors.directExecutor(); + + int nextTask = 1; + Set runningTasks = ConcurrentHashMap.newKeySet(); + runningTasks.add(nextTask); + + ListenableFuture nonFailingTask = new ListenableFutureService().succeedingTask(); + nonFailingTask.addListener(() -> runningTasks.remove(nextTask), listeningExecutor); + + assertTrue(runningTasks.isEmpty()); + } + + @Test + public void givenFailingTask_whenDirectListen_thenListenerExecutes() { + final Executor listeningExecutor = MoreExecutors.directExecutor(); + + int nextTask = 1; + Set runningTasks = ConcurrentHashMap.newKeySet(); + runningTasks.add(nextTask); + + final ListenableFuture failingTask = new ListenableFutureService().failingTask(); + failingTask.addListener(() -> runningTasks.remove(nextTask),listeningExecutor); + + assertTrue(runningTasks.isEmpty()); + } +} \ No newline at end of file diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml index 957b8ad166..8ffac98b51 100644 --- a/guava-modules/pom.xml +++ b/guava-modules/pom.xml @@ -24,6 +24,7 @@ guava-collections-list guava-collections-map guava-collections-set + guava-concurrency guava-io From 0821fb646cc1ea9a923335e7b226470a7bcc33af Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 10 Jul 2021 18:54:09 +0530 Subject: [PATCH 068/114] JAVA-5935: Analyse bean overriding fix in modules - Part 3 --- .../spring-boot-mvc-2/src/main/resources/application.properties | 1 - .../spring-boot-mvc/src/main/resources/application.properties | 1 - .../src/main/resources/application.properties | 1 - .../src/test/resources/application.properties | 1 - .../src/main/resources/application.properties | 1 - 5 files changed, 5 deletions(-) diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-mvc-2/src/main/resources/application.properties index 7070d4c2f0..3ee7660e8b 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/resources/application.properties @@ -1,4 +1,3 @@ -spring.main.allow-bean-definition-overriding=true spring.mvc.static-path-pattern=/content/** spring.webflux.static-path-pattern=/content/** spring.resources.static-locations=classpath:/files/,classpath:/static-files \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties index 6dab470c84..7f399bb11d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/application.properties @@ -1,2 +1 @@ -spring.main.allow-bean-definition-overriding=true spring.thymeleaf.view-names=thymeleaf/* \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime/src/main/resources/application.properties b/spring-boot-modules/spring-boot-runtime/src/main/resources/application.properties index 27b7915cff..2bf15543f0 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-runtime/src/main/resources/application.properties @@ -3,5 +3,4 @@ management.metrics.enable.root=true management.metrics.enable.jvm=true management.endpoint.restart.enabled=true spring.datasource.jmx-enabled=false -spring.main.allow-bean-definition-overriding=true management.endpoint.shutdown.enabled=true \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime/src/test/resources/application.properties b/spring-boot-modules/spring-boot-runtime/src/test/resources/application.properties index cf0f0ab74c..7bf9450088 100644 --- a/spring-boot-modules/spring-boot-runtime/src/test/resources/application.properties +++ b/spring-boot-modules/spring-boot-runtime/src/test/resources/application.properties @@ -8,5 +8,4 @@ endpoints.shutdown.enabled=true management.endpoint.restart.enabled=true -spring.main.allow-bean-definition-overriding=true spring.jmx.unique-names=true \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing/src/main/resources/application.properties b/spring-boot-modules/spring-boot-testing/src/main/resources/application.properties index daab3e8d2c..70cae370a4 100644 --- a/spring-boot-modules/spring-boot-testing/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-testing/src/main/resources/application.properties @@ -6,4 +6,3 @@ spring.redis.port= 6379 spring.security.user.name=john spring.security.user.password=123 -spring.main.allow-bean-definition-overriding=true \ No newline at end of file From 0eb7183ecd2511b3be0825e43332291d6ffd8645 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 10 Jul 2021 21:10:43 +0530 Subject: [PATCH 069/114] JAVA-5936: Analyse bean overriding fix in modules - Part 4 --- .../src/main/resources/application.properties | 2 -- .../src/main/resources/application.properties | 1 - 2 files changed, 3 deletions(-) diff --git a/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties index 18ef8d4e60..3829f676d3 100644 --- a/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties @@ -1,5 +1,3 @@ -spring.main.allow-bean-definition-overriding=true - spring.jpa.properties.hibernate.jdbc.batch_size=4 spring.jpa.properties.hibernate.order_inserts=true spring.jpa.properties.hibernate.order_updates=true diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties index 29326c6061..32d3e640f9 100644 --- a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties @@ -10,7 +10,6 @@ spring.datasource.url=jdbc:h2:mem:baeldung #spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true -spring.main.allow-bean-definition-overriding=true #hibernate.dialect=org.hibernate.dialect.H2Dialect spring.jpa.properties.hibernate.id.new_generator_mappings=false \ No newline at end of file From 218f67ef4c8146a3c98ef3f5f306ffb748154669 Mon Sep 17 00:00:00 2001 From: "Amitabh.Tiwari" Date: Sun, 11 Jul 2021 12:15:12 +0530 Subject: [PATCH 070/114] Added changes as per review --- .../StringToBigIntegerUnitTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java index 8d47d72a0e..82ffe96d84 100644 --- a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtobybiginteger/StringToBigIntegerUnitTest.java @@ -10,33 +10,33 @@ public class StringToBigIntegerUnitTest { @Test public void whenGetStringWithOutRadix_thenOK() { - final String inputString = "878"; + String inputString = "878"; BigInteger result = new BigInteger(inputString); assertEquals("878", result.toString()); } @Test public void whenGetStringWithRadix_thenOK() { - final String inputString = "290f98"; + String inputString = "290f98"; BigInteger result = new BigInteger(inputString, 16); assertEquals("2690968", result.toString()); } @Test(expected = NumberFormatException.class) public void whenGetStringWithOutRadix_thenThrowError() { - final String inputString = "290f98"; + String inputString = "290f98"; new BigInteger(inputString); } @Test(expected = NumberFormatException.class) public void whenGetStringWithRadix_thenThrowError() { - final String inputString = "290f98"; + String inputString = "290f98"; new BigInteger(inputString, 7); } @Test public void whenGetStringUsingByte_thenOk() { - final String inputString = "290f98"; + String inputString = "290f98"; byte[] inputStringBytes = inputString.getBytes(); BigInteger result = new BigInteger(inputStringBytes); assertEquals("290f98", new String(result.toByteArray())); From 4f3f287923f5819cadae80817d0074f2c80d85a9 Mon Sep 17 00:00:00 2001 From: Daniel Strmecki Date: Sun, 11 Jul 2021 15:18:10 +0200 Subject: [PATCH 071/114] Feature/bael 4911 tiered compilation (#10958) * BASE-4911: Tiered Compilation Initial Commit * BASE-4911: Use Generics --- core-java-modules/core-java-lang-4/pom.xml | 10 +++++++++ .../baeldung/tieredcompilation/Article.java | 21 +++++++++++++++++++ .../baeldung/tieredcompilation/Formatter.java | 7 +++++++ .../tieredcompilation/JsonFormatter.java | 15 +++++++++++++ .../tieredcompilation/TieredCompilation.java | 17 +++++++++++++++ .../tieredcompilation/XmlFormatter.java | 15 +++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Article.java create mode 100644 core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Formatter.java create mode 100644 core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/JsonFormatter.java create mode 100644 core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/TieredCompilation.java create mode 100644 core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/XmlFormatter.java diff --git a/core-java-modules/core-java-lang-4/pom.xml b/core-java-modules/core-java-lang-4/pom.xml index 4e692ffa55..46ad335568 100644 --- a/core-java-modules/core-java-lang-4/pom.xml +++ b/core-java-modules/core-java-lang-4/pom.xml @@ -21,6 +21,16 @@ jmh-core ${jmh-core.version} + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + org.openjdk.jmh jmh-generator-annprocess diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Article.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Article.java new file mode 100644 index 0000000000..2eca40f055 --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Article.java @@ -0,0 +1,21 @@ +package com.baeldung.tieredcompilation; + +public class Article { + + private String name; + private String author; + + public Article(String name, String author) { + this.name = name; + this.author = author; + } + + public String getName() { + return name; + } + + public String getAuthor() { + return author; + } + +} diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Formatter.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Formatter.java new file mode 100644 index 0000000000..ee5d74d5fe --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/Formatter.java @@ -0,0 +1,7 @@ +package com.baeldung.tieredcompilation; + +public interface Formatter { + + String format(T object) throws Exception; + +} diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/JsonFormatter.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/JsonFormatter.java new file mode 100644 index 0000000000..9951b477da --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/JsonFormatter.java @@ -0,0 +1,15 @@ +package com.baeldung.tieredcompilation; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.json.JsonMapper; + +public class JsonFormatter implements Formatter { + + private static final JsonMapper mapper = new JsonMapper(); + + @Override + public String format(T object) throws JsonProcessingException { + return mapper.writeValueAsString(object); + } + +} diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/TieredCompilation.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/TieredCompilation.java new file mode 100644 index 0000000000..ea7178051e --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/TieredCompilation.java @@ -0,0 +1,17 @@ +package com.baeldung.tieredcompilation; + +public class TieredCompilation { + + public static void main(String[] args) throws Exception { + for (int i = 0; i < 1_000_000; i++) { + Formatter formatter; + if (i < 500_000) { + formatter = new JsonFormatter(); + } else { + formatter = new XmlFormatter(); + } + formatter.format(new Article("Tiered Compilation in JVM", "Baeldung")); + } + } + +} diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/XmlFormatter.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/XmlFormatter.java new file mode 100644 index 0000000000..8b9823cd88 --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/tieredcompilation/XmlFormatter.java @@ -0,0 +1,15 @@ +package com.baeldung.tieredcompilation; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +public class XmlFormatter implements Formatter { + + private static final XmlMapper mapper = new XmlMapper(); + + @Override + public String format(T object) throws JsonProcessingException { + return mapper.writeValueAsString(object); + } + +} From 181834efeb279f8cc113316f064172bd04cb1b59 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 12 Jul 2021 22:52:58 +0530 Subject: [PATCH 072/114] JAVA-5937: Analyse bean overriding fix in modules - Part 5 --- .../src/main/resources/application.properties | 1 - .../src/main/resources/application.properties | 2 -- .../src/main/resources/application.properties | 1 - 3 files changed, 4 deletions(-) delete mode 100644 spring-security-modules/spring-security-core/src/main/resources/application.properties delete mode 100644 spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties diff --git a/spring-security-modules/spring-security-core/src/main/resources/application.properties b/spring-security-modules/spring-security-core/src/main/resources/application.properties deleted file mode 100644 index 709574239b..0000000000 --- a/spring-security-modules/spring-security-core/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties index aca20f4e3c..fcdaabe007 100644 --- a/spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties +++ b/spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties @@ -1,5 +1,3 @@ -spring.main.allow-bean-definition-overriding=true - spring.mail.host=localhost spring.mail.port=8025 diff --git a/spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties deleted file mode 100644 index 709574239b..0000000000 --- a/spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.main.allow-bean-definition-overriding=true \ No newline at end of file From 611d074aa430a5e272d5f53c7f68bed0ebffc5fc Mon Sep 17 00:00:00 2001 From: Haroon Khan Date: Tue, 13 Jul 2021 13:34:34 +0100 Subject: [PATCH 073/114] [BAEL-4823] Maven plugin management (#10957) * [BAEL-4823] Maven plugin management * [BAEL-4823] Minor code cleanup --- maven-modules/plugin-management/pom.xml | 63 +++++++++++++++++++ .../plugin-management/submodule-1/pom.xml | 23 +++++++ .../submodule-1/src/resources/include.json | 3 + .../CopiesAdditionalResourcesUnitTest.java | 19 ++++++ .../plugin-management/submodule-2/pom.xml | 14 +++++ maven-modules/pom.xml | 1 + 6 files changed, 123 insertions(+) create mode 100644 maven-modules/plugin-management/pom.xml create mode 100644 maven-modules/plugin-management/submodule-1/pom.xml create mode 100644 maven-modules/plugin-management/submodule-1/src/resources/include.json create mode 100644 maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java create mode 100644 maven-modules/plugin-management/submodule-2/pom.xml diff --git a/maven-modules/plugin-management/pom.xml b/maven-modules/plugin-management/pom.xml new file mode 100644 index 0000000000..4a999a1aae --- /dev/null +++ b/maven-modules/plugin-management/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + 0.0.1-SNAPSHOT + + maven-modules + com.baeldung + 0.0.1-SNAPSHOT + + plugin-management + pom + + + submodule-1 + submodule-2 + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${maven.bulid.helper.plugin} + + + add-resource + generate-resources + + add-resource + + + + + src/resources + json + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin} + + 1.8 + 1.8 + + + + + + + + 3.8.1 + 3.2.0 + + + \ No newline at end of file diff --git a/maven-modules/plugin-management/submodule-1/pom.xml b/maven-modules/plugin-management/submodule-1/pom.xml new file mode 100644 index 0000000000..915e4dfe60 --- /dev/null +++ b/maven-modules/plugin-management/submodule-1/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + submodule-1 + + + plugin-management + com.baeldung + 0.0.1-SNAPSHOT + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + + diff --git a/maven-modules/plugin-management/submodule-1/src/resources/include.json b/maven-modules/plugin-management/submodule-1/src/resources/include.json new file mode 100644 index 0000000000..d5df76e7e0 --- /dev/null +++ b/maven-modules/plugin-management/submodule-1/src/resources/include.json @@ -0,0 +1,3 @@ +{ + "key": "value" +} \ No newline at end of file diff --git a/maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java b/maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java new file mode 100644 index 0000000000..ab6b781790 --- /dev/null +++ b/maven-modules/plugin-management/submodule-1/src/test/java/com/baeldung/CopiesAdditionalResourcesUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CopiesAdditionalResourcesUnitTest { + + @Test + void givenAdditionalResource_whenCopyingFromSourceToDestination_thenShouldBeInDestination() { + URL resource = getClass().getClassLoader().getResource("json/include.json"); + File destinationFile = new File(resource.getFile()); + + assertTrue(destinationFile.exists()); + } +} diff --git a/maven-modules/plugin-management/submodule-2/pom.xml b/maven-modules/plugin-management/submodule-2/pom.xml new file mode 100644 index 0000000000..327bdcebb1 --- /dev/null +++ b/maven-modules/plugin-management/submodule-2/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + submodule-2 + + + plugin-management + com.baeldung + 0.0.1-SNAPSHOT + + + diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index 7e8bf20553..0700c6e637 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -33,6 +33,7 @@ versions-maven-plugin maven-printing-plugins maven-builder-plugin + plugin-management From 628cfcdea192e624c7fc15dfacf53fd6b62af119 Mon Sep 17 00:00:00 2001 From: Liam Garvie Date: Tue, 13 Jul 2021 17:39:53 +0100 Subject: [PATCH 074/114] BAEL-4908 added code for pubsub vs message queues tutorial --- rabbitmq/pom.xml | 26 ++++++++- .../pubsubmq/client/ClientApplication.java | 43 ++++++++++++++ .../baeldung/pubsubmq/client/Consumer.java | 7 +++ .../baeldung/pubsubmq/server/Publisher.java | 28 +++++++++ .../pubsubmq/server/ServerApplication.java | 57 +++++++++++++++++++ 5 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 rabbitmq/src/main/java/com/baeldung/pubsubmq/client/ClientApplication.java create mode 100644 rabbitmq/src/main/java/com/baeldung/pubsubmq/client/Consumer.java create mode 100644 rabbitmq/src/main/java/com/baeldung/pubsubmq/server/Publisher.java create mode 100644 rabbitmq/src/main/java/com/baeldung/pubsubmq/server/ServerApplication.java diff --git a/rabbitmq/pom.xml b/rabbitmq/pom.xml index ed45029d3c..ae38d697f6 100644 --- a/rabbitmq/pom.xml +++ b/rabbitmq/pom.xml @@ -9,20 +9,42 @@ com.baeldung - parent-modules - 1.0.0-SNAPSHOT + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + com.rabbitmq amqp-client ${amqp-client.version} + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-starter-amqp + 5.12.0 + 2020.0.3 \ No newline at end of file diff --git a/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/ClientApplication.java b/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/ClientApplication.java new file mode 100644 index 0000000000..e8acb90f00 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/ClientApplication.java @@ -0,0 +1,43 @@ +package com.baeldung.pubsubmq.client; + +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + + +@SpringBootApplication +public class ClientApplication { + private static final String MESSAGE_QUEUE = "pizza-message-queue"; + + @Bean + public Queue queue() { + return new Queue(MESSAGE_QUEUE); + } + + @Bean + public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + container.setQueueNames(MESSAGE_QUEUE); + container.setMessageListener(listenerAdapter); + return container; + } + + @Bean + public Consumer consumer() { + return new Consumer(); + } + + @Bean + public MessageListenerAdapter listenerAdapter(Consumer consumer) { + return new MessageListenerAdapter(consumer, "receiveOrder"); + } + + public static void main(String[] args) { + SpringApplication.run(ClientApplication.class, args); + } +} diff --git a/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/Consumer.java b/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/Consumer.java new file mode 100644 index 0000000000..fadc60572d --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/pubsubmq/client/Consumer.java @@ -0,0 +1,7 @@ +package com.baeldung.pubsubmq.client; + +public class Consumer { + public void receiveOrder(String message) { + System.out.printf("Order received: %s%n", message); + } +} diff --git a/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/Publisher.java b/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/Publisher.java new file mode 100644 index 0000000000..24c4be0a70 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/Publisher.java @@ -0,0 +1,28 @@ +package com.baeldung.pubsubmq.server; + +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import javax.annotation.PostConstruct; + +public class Publisher { + + private RabbitTemplate rabbitTemplate; + private String queue; + private String topic; + + public Publisher(RabbitTemplate rabbitTemplate, String queue, String topic) { + this.rabbitTemplate = rabbitTemplate; + this.queue = queue; + this.topic = topic; + } + + @PostConstruct + public void postMessages() { + rabbitTemplate.convertAndSend(queue, "1 Pepperoni"); + rabbitTemplate.convertAndSend(queue, "3 Margarita"); + rabbitTemplate.convertAndSend(queue, "1 Ham and Pineapple (yuck)"); + + rabbitTemplate.convertAndSend(topic, "notification", "New Deal on T-Shirts: 95% off!"); + rabbitTemplate.convertAndSend(topic, "notification", "2 for 1 on all Jeans!"); + } +} diff --git a/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/ServerApplication.java b/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/ServerApplication.java new file mode 100644 index 0000000000..f2387f6ae5 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/pubsubmq/server/ServerApplication.java @@ -0,0 +1,57 @@ +package com.baeldung.pubsubmq.server; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class ServerApplication { + private static final String MESSAGE_QUEUE = "pizza-message-queue"; + private static final String PUB_SUB_TOPIC = "notification-topic"; + private static final String PUB_SUB_EMAIL_QUEUE = "email-queue"; + private static final String PUB_SUB_TEXT_QUEUE = "text-queue"; + + @Bean + public Queue queue() { + return new Queue(MESSAGE_QUEUE); + } + + @Bean + public Queue emailQueue() { + return new Queue(PUB_SUB_EMAIL_QUEUE); + } + + @Bean + public Queue textQueue() { + return new Queue(PUB_SUB_TEXT_QUEUE); + } + + @Bean + public TopicExchange exchange() { + return new TopicExchange(PUB_SUB_TOPIC); + } + + @Bean + public Binding emailBinding(Queue emailQueue, TopicExchange exchange) { + return BindingBuilder.bind(emailQueue).to(exchange).with("notification"); + } + + @Bean + public Binding textBinding(Queue textQueue, TopicExchange exchange) { + return BindingBuilder.bind(textQueue).to(exchange).with("notification"); + } + + @Bean + public Publisher publisher(RabbitTemplate rabbitTemplate) { + return new Publisher(rabbitTemplate, MESSAGE_QUEUE, PUB_SUB_TOPIC); + } + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class, args); + } +} From a2390f614622d66f91010fae75a7541d8f16765f Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Wed, 14 Jul 2021 03:19:47 +0430 Subject: [PATCH 075/114] BAEL-4851: Update "DB Integration Tests with Spring Boot and Testcontainers" article (#11015) --- .../daos/UserRepositoryTCJdbcLiveTest.java | 46 +++++++++++++++++++ .../test/resources/application-tc-jdbc.yml | 6 +++ 2 files changed, 52 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java create mode 100644 persistence-modules/spring-data-jpa-enterprise/src/test/resources/application-tc-jdbc.yml diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java new file mode 100644 index 0000000000..c976590966 --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java @@ -0,0 +1,46 @@ +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.daos.user.UserRepository; +import com.baeldung.boot.domain.User; +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.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@ActiveProfiles("tc-jdbc") +@SpringBootTest(classes = Application.class) +public class UserRepositoryTCJdbcLiveTest { + + final String USER_EMAIL = "email@example.com"; + final String USER_EMAIL2 = "email2@example.com"; + final String USER_EMAIL3 = "email3@example.com"; + final String USER_EMAIL4 = "email4@example.com"; + final Integer INACTIVE_STATUS = 0; + final Integer ACTIVE_STATUS = 1; + + @Autowired + private UserRepository userRepository; + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationNative_ThenModifyMatchingUsers() { + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS)); + userRepository.flush(); + + int updatedUsersSize = userRepository.updateUserSetStatusForNameNativePostgres(INACTIVE_STATUS, "SAMPLE"); + + assertThat(updatedUsersSize).isEqualTo(2); + } +} diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/resources/application-tc-jdbc.yml b/persistence-modules/spring-data-jpa-enterprise/src/test/resources/application-tc-jdbc.yml new file mode 100644 index 0000000000..ad5906fa6e --- /dev/null +++ b/persistence-modules/spring-data-jpa-enterprise/src/test/resources/application-tc-jdbc.yml @@ -0,0 +1,6 @@ +spring: + datasource: + url: jdbc:tc:postgresql:11.1:///integration-tests-db + jpa: + hibernate: + ddl-auto: create \ No newline at end of file From 66b9668e7e2a81129205c250f3091f72afca9679 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 14 Jul 2021 21:48:12 +0800 Subject: [PATCH 076/114] Create README.md --- core-java-modules/core-java-streams-4/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 core-java-modules/core-java-streams-4/README.md diff --git a/core-java-modules/core-java-streams-4/README.md b/core-java-modules/core-java-streams-4/README.md new file mode 100644 index 0000000000..6eeee943aa --- /dev/null +++ b/core-java-modules/core-java-streams-4/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Count Occurrences Using Java groupingBy Collector](https://www.baeldung.com/java-groupingby-count) From b3015ed6e05561b6e6bc146c85c99f52633073c8 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 14 Jul 2021 21:51:34 +0800 Subject: [PATCH 077/114] Update README.md --- core-java-modules/core-java-string-conversions-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-conversions-2/README.md b/core-java-modules/core-java-string-conversions-2/README.md index 3bd3ba927e..229a40f91f 100644 --- a/core-java-modules/core-java-string-conversions-2/README.md +++ b/core-java-modules/core-java-string-conversions-2/README.md @@ -7,4 +7,5 @@ This module contains articles about string conversions from/to another type. - [Convert String to Byte Array and Reverse in Java](https://www.baeldung.com/java-string-to-byte-array) - [Convert Character Array to String in Java](https://www.baeldung.com/java-char-array-to-string) - [Converting String to BigDecimal in Java](https://www.baeldung.com/java-string-to-bigdecimal) +- [Converting String to BigInteger in Java](https://www.baeldung.com/java-string-to-biginteger) - More articles: [[<-- prev]](/core-java-string-conversions) From 3a8f5407c84ba5ff4eb6f56427f15be7a2015005 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 14 Jul 2021 21:52:59 +0800 Subject: [PATCH 078/114] Update README.md --- core-java-modules/core-java-lang-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-lang-4/README.md b/core-java-modules/core-java-lang-4/README.md index 18bbf43647..562be950c0 100644 --- a/core-java-modules/core-java-lang-4/README.md +++ b/core-java-modules/core-java-lang-4/README.md @@ -7,3 +7,4 @@ This module contains articles about core features in the Java language - [What are Compile-time Constants in Java?](https://www.baeldung.com/java-compile-time-constants) - [Java Objects.hash() vs Objects.hashCode()](https://www.baeldung.com/java-objects-hash-vs-objects-hashcode) - [Referencing a Method in Javadoc Comments](https://www.baeldung.com/java-method-in-javadoc) +- [Tiered Compilation in JVM](https://www.baeldung.com/jvm-tiered-compilation) From 471ff477bdb3eeaec760daae38a1b0e09a450e3d Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 14 Jul 2021 21:56:30 +0800 Subject: [PATCH 079/114] Update README.md --- core-java-modules/core-java-lang-oop-modifiers/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-lang-oop-modifiers/README.md b/core-java-modules/core-java-lang-oop-modifiers/README.md index eef905fa0e..1f37cc903e 100644 --- a/core-java-modules/core-java-lang-oop-modifiers/README.md +++ b/core-java-modules/core-java-lang-oop-modifiers/README.md @@ -9,4 +9,5 @@ This module contains articles about modifiers in Java - [The “final†Keyword in Java](https://www.baeldung.com/java-final) - [A Guide to the Static Keyword in Java](https://www.baeldung.com/java-static) - [Static and Default Methods in Interfaces in Java](https://www.baeldung.com/java-static-default-methods) -- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp) \ No newline at end of file +- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp) +- [Static Classes Versus the Singleton Pattern in Java](https://www.baeldung.com/java-static-class-vs-singleton) From 895def1797d5dc32bff9743a82a44ec268bda9de Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 15 Jul 2021 01:21:54 +0800 Subject: [PATCH 080/114] Create README.md --- maven-modules/maven-builder-plugin/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 maven-modules/maven-builder-plugin/README.md diff --git a/maven-modules/maven-builder-plugin/README.md b/maven-modules/maven-builder-plugin/README.md new file mode 100644 index 0000000000..47cd99d281 --- /dev/null +++ b/maven-modules/maven-builder-plugin/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Additional Source Directories in Maven](https://www.baeldung.com/maven-add-src-directories) From 0a3c6a675d2c6b53acc5373bd6e8266cad28c058 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Thu, 15 Jul 2021 07:15:36 +0430 Subject: [PATCH 081/114] BAEL-5026: Improvement for Write an InputStream to a File (#11018) --- .../inputstreamtostring/JavaInputStreamToXUnitTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java index dbce18ee5e..03f528766b 100644 --- a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java +++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java @@ -21,11 +21,11 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; -import java.io.StringReader; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Scanner; import java.util.UUID; @@ -165,15 +165,13 @@ public class JavaInputStreamToXUnitTest { @Test public final void whenConvertingToFile_thenCorrect() throws IOException { - final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); - final byte[] buffer = new byte[initialStream.available()]; - initialStream.read(buffer); + final Path path = Paths.get("src/test/resources/sample.txt"); + final byte[] buffer = java.nio.file.Files.readAllBytes(path); final File targetFile = new File("src/test/resources/targetFile.tmp"); final OutputStream outStream = new FileOutputStream(targetFile); outStream.write(buffer); - IOUtils.closeQuietly(initialStream); IOUtils.closeQuietly(outStream); } From 48bef2c7974cd7e8d9d8a152a1b111c1c6ec099d Mon Sep 17 00:00:00 2001 From: Azhwani <13301425+azhwani@users.noreply.github.com> Date: Thu, 15 Jul 2021 06:18:47 +0200 Subject: [PATCH 082/114] BAEL-4969: Improvement: Streams to Immutable Collections (#11026) * add new module for java core 16 * format pom.xml --- core-java-modules/core-java-16/README.md | 3 ++ core-java-modules/core-java-16/pom.xml | 48 +++++++++++++++++++ .../streams/StreamToImmutableUnitTest.java | 23 +++++++++ 3 files changed, 74 insertions(+) create mode 100644 core-java-modules/core-java-16/README.md create mode 100644 core-java-modules/core-java-16/pom.xml create mode 100644 core-java-modules/core-java-16/src/test/java/com/baeldung/streams/StreamToImmutableUnitTest.java diff --git a/core-java-modules/core-java-16/README.md b/core-java-modules/core-java-16/README.md new file mode 100644 index 0000000000..760513189f --- /dev/null +++ b/core-java-modules/core-java-16/README.md @@ -0,0 +1,3 @@ +### Relevant articles: + +- [Collect a Java Stream to an Immutable Collection](https://www.baeldung.com/java-stream-immutable-collection) diff --git a/core-java-modules/core-java-16/pom.xml b/core-java-modules/core-java-16/pom.xml new file mode 100644 index 0000000000..230e342f01 --- /dev/null +++ b/core-java-modules/core-java-16/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + core-java-16 + 0.1.0-SNAPSHOT + core-java-16 + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + + + + + 16 + 16 + 3.6.1 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/streams/StreamToImmutableUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/streams/StreamToImmutableUnitTest.java new file mode 100644 index 0000000000..afd7369d8d --- /dev/null +++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/streams/StreamToImmutableUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.streams; + +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class StreamToImmutableUnitTest { + + @Test + public void whenUsingStreamToList_thenReturnImmutableList() { + + List immutableList = Stream.of("a", "b", "c", "d") + .toList(); + + Assertions.assertThrows(UnsupportedOperationException.class, () -> { + immutableList.add("e"); + }); + + } + +} From 978bf7f543d8cf4a55e68bd0c8b6b05b407a2822 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Thu, 15 Jul 2021 19:09:30 +0200 Subject: [PATCH 083/114] JAVA-6348: Properly ignore a unit test (#11031) Co-authored-by: Krzysztof Woyke --- .../java11/httpclient/test/HttpRequestUnitTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java index a3a5592cd9..3b9db284c8 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java @@ -17,8 +17,8 @@ import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.time.Duration; +import org.junit.Ignore; import org.junit.Test; -import org.junit.jupiter.api.Disabled; public class HttpRequestUnitTest { @@ -51,10 +51,10 @@ public class HttpRequestUnitTest { /* * This test will fail as soon as the given URL returns a HTTP 2 response. - * Therefore, let's leave it commented out. + * Therefore, let's leave it ignored. * */ - @Test - @Disabled + @Test + @Ignore public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException { HttpRequest request = HttpRequest.newBuilder() .uri(new URI("https://postman-echo.com/get")) From 17814a1468002d8e9a844a4696fa73808189c927 Mon Sep 17 00:00:00 2001 From: Arash Ariani Date: Sat, 17 Jul 2021 14:11:26 +0430 Subject: [PATCH 084/114] BAEL-4464 : how to implement LRU-Cache in java codes added (#11036) * BAEL-4464 : how to implement LRU-Cache in java codes added * BAEL-4464 : how to implement LRU-Cache in java codes added - package named fixed * BAEL-4464 : how to implement LRU-Cache in java codes added - package named changed * BAEL-4464 : how to implement LRU-Cache in java codes added - unitTest fixed --- .../java/com/baeldung/lrucache/Cache.java | 15 ++ .../com/baeldung/lrucache/CacheElement.java | 31 ++++ .../baeldung/lrucache/DoublyLinkedList.java | 168 ++++++++++++++++++ .../java/com/baeldung/lrucache/DummyNode.java | 62 +++++++ .../java/com/baeldung/lrucache/LRUCache.java | 105 +++++++++++ .../com/baeldung/lrucache/LinkedListNode.java | 23 +++ .../main/java/com/baeldung/lrucache/Node.java | 71 ++++++++ .../baeldung/lrucache/LRUCacheUnitTest.java | 59 ++++++ 8 files changed, 534 insertions(+) create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/Cache.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/CacheElement.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/DummyNode.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/LinkedListNode.java create mode 100644 data-structures/src/main/java/com/baeldung/lrucache/Node.java create mode 100644 data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java diff --git a/data-structures/src/main/java/com/baeldung/lrucache/Cache.java b/data-structures/src/main/java/com/baeldung/lrucache/Cache.java new file mode 100644 index 0000000000..f070f66191 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/Cache.java @@ -0,0 +1,15 @@ +package com.baeldung.lrucache; + +import java.util.Optional; + +public interface Cache { + boolean put(K key, V value); + + Optional get(K key); + + int size(); + + boolean isEmpty(); + + void clear(); +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/CacheElement.java b/data-structures/src/main/java/com/baeldung/lrucache/CacheElement.java new file mode 100644 index 0000000000..7d260c4531 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/CacheElement.java @@ -0,0 +1,31 @@ +package com.baeldung.lrucache; + +/** + * Created by arash on 09.07.21. + */ + +public class CacheElement { + private K key; + private V value; + + public CacheElement(K key, V value) { + this.value = value; + this.key = key; + } + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java b/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java new file mode 100644 index 0000000000..a2b56741a2 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java @@ -0,0 +1,168 @@ +package com.baeldung.lrucache; + +import java.util.Collection; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class DoublyLinkedList { + + private DummyNode dummyNode; + private LinkedListNode head; + private LinkedListNode tail; + private AtomicInteger size; + private ReentrantReadWriteLock.ReadLock readLock; + private ReentrantReadWriteLock.WriteLock writeLock; + + + public DoublyLinkedList() { + this.dummyNode = new DummyNode(this); + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + readLock = lock.readLock(); + writeLock = lock.writeLock(); + clear(); + } + + public void clear() { + writeLock.lock(); + try { + head = dummyNode; + tail = dummyNode; + size = new AtomicInteger(0); + } finally { + writeLock.unlock(); + } + } + + public int size() { + readLock.lock(); + try { + return size.get(); + } finally { + readLock.unlock(); + } + } + + public boolean isEmpty() { + readLock.lock(); + try { + return head.isEmpty(); + } finally { + readLock.unlock(); + } + } + + public boolean contains(T value) { + readLock.lock(); + try { + return search(value).hasElement(); + } finally { + readLock.unlock(); + } + } + + public LinkedListNode search(T value) { + readLock.lock(); + try { + return head.search(value); + } finally { + readLock.unlock(); + } + } + + public LinkedListNode add(T value) { + writeLock.lock(); + try { + head = new Node(value, head, this); + if (tail.isEmpty()) { + tail = head; + } + size.incrementAndGet(); + return head; + } finally { + writeLock.unlock(); + } + } + + public boolean addAll(Collection values) { + writeLock.lock(); + try { + for (T value : values) { + if (add(value).isEmpty()) { + return false; + } + } + return true; + } finally { + writeLock.unlock(); + } + } + + public LinkedListNode remove(T value) { + writeLock.lock(); + try { + LinkedListNode linkedListNode = head.search(value); + if (!linkedListNode.isEmpty()) { + if (linkedListNode == tail) { + tail = tail.getPrev(); + } + if (linkedListNode == head) { + head = head.getNext(); + } + linkedListNode.detach(); + size.decrementAndGet(); + } + return linkedListNode; + } finally { + writeLock.unlock(); + } + } + + public LinkedListNode removeTail() { + writeLock.lock(); + try { + LinkedListNode oldTail = tail; + if (oldTail == head) { + tail = head = dummyNode; + } else { + tail = tail.getPrev(); + oldTail.detach(); + } + if (!oldTail.isEmpty()) { + size.decrementAndGet(); + } + return oldTail; + } finally { + writeLock.unlock(); + } + } + + public LinkedListNode moveToFront(LinkedListNode node) { + return node.isEmpty() ? dummyNode : updateAndMoveToFront(node, node.getElement()); + } + + public LinkedListNode updateAndMoveToFront(LinkedListNode node, T newValue) { + writeLock.lock(); + try { + if (node.isEmpty() || (this != (node.getListReference()))) { + return dummyNode; + } + detach(node); + add(newValue); + return head; + } finally { + writeLock.unlock(); + } + } + + private void detach(LinkedListNode node) { + if (node != tail) { + node.detach(); + if (node == head) { + head = head.getNext(); + } + size.decrementAndGet(); + } else { + removeTail(); + } + } +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/DummyNode.java b/data-structures/src/main/java/com/baeldung/lrucache/DummyNode.java new file mode 100644 index 0000000000..4965b70bcf --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/DummyNode.java @@ -0,0 +1,62 @@ +package com.baeldung.lrucache; + +/** + * Created by arash on 09.07.21. + */ +public class DummyNode implements LinkedListNode { + private DoublyLinkedList list; + + public DummyNode(DoublyLinkedList list) { + this.list = list; + } + + @Override + public boolean hasElement() { + return false; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public T getElement() throws NullPointerException { + throw new NullPointerException(); + } + + @Override + public void detach() { + return; + } + + @Override + public DoublyLinkedList getListReference() { + return list; + } + + @Override + public LinkedListNode setPrev(LinkedListNode next) { + return next; + } + + @Override + public LinkedListNode setNext(LinkedListNode prev) { + return prev; + } + + @Override + public LinkedListNode getPrev() { + return this; + } + + @Override + public LinkedListNode getNext() { + return this; + } + + @Override + public LinkedListNode search(T value) { + return this; + } +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java b/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java new file mode 100644 index 0000000000..0128cadf78 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java @@ -0,0 +1,105 @@ +package com.baeldung.lrucache; + +import java.util.Hashtable; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class LRUCache implements Cache { + private int size; + private Map>> linkedListNodeMap; + private DoublyLinkedList> doublyLinkedList; + private ReentrantReadWriteLock.ReadLock readLock; + private ReentrantReadWriteLock.WriteLock writeLock; + + public LRUCache(int size) { + this.size = size; + this.linkedListNodeMap = new Hashtable<>(size); + this.doublyLinkedList = new DoublyLinkedList<>(); + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + this.readLock = lock.readLock(); + this.writeLock = lock.writeLock(); + } + + @Override + public boolean put(K key, V value) { + writeLock.lock(); + try { + CacheElement item = new CacheElement(key, value); + LinkedListNode> newNode; + if (this.linkedListNodeMap.containsKey(key)) { + LinkedListNode> node = this.linkedListNodeMap.get(key); + newNode = doublyLinkedList.updateAndMoveToFront(node, item); + } else { + if (this.size() >= this.size) { + this.evictElement(); + } + newNode = this.doublyLinkedList.add(item); + } + if (newNode.isEmpty()) { + return false; + } + this.linkedListNodeMap.put(key, newNode); + return true; + } finally { + writeLock.unlock(); + } + } + + @Override + public Optional get(K key) { + readLock.lock(); + try { + LinkedListNode> linkedListNode = this.linkedListNodeMap.get(key); + if (linkedListNode != null && !linkedListNode.isEmpty()) { + linkedListNodeMap.put(key, this.doublyLinkedList.moveToFront(linkedListNode)); + return Optional.of(linkedListNode.getElement().getValue()); + } + return Optional.empty(); + } finally { + readLock.unlock(); + } + } + + @Override + public int size() { + readLock.lock(); + try { + return doublyLinkedList.size(); + } finally { + readLock.unlock(); + } + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public void clear() { + writeLock.lock(); + try { + linkedListNodeMap.clear(); + doublyLinkedList.clear(); + } finally { + writeLock.unlock(); + } + } + + + private boolean evictElement() { + writeLock.lock(); + try { + LinkedListNode> linkedListNode = doublyLinkedList.removeTail(); + if (linkedListNode.isEmpty()) { + return false; + } + linkedListNodeMap.remove(linkedListNode.getElement().getKey()); + return true; + } finally { + writeLock.unlock(); + } + } +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/LinkedListNode.java b/data-structures/src/main/java/com/baeldung/lrucache/LinkedListNode.java new file mode 100644 index 0000000000..219ee13496 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/LinkedListNode.java @@ -0,0 +1,23 @@ +package com.baeldung.lrucache; + +public interface LinkedListNode { + boolean hasElement(); + + boolean isEmpty(); + + V getElement() throws NullPointerException; + + void detach(); + + DoublyLinkedList getListReference(); + + LinkedListNode setPrev(LinkedListNode prev); + + LinkedListNode setNext(LinkedListNode next); + + LinkedListNode getPrev(); + + LinkedListNode getNext(); + + LinkedListNode search(V value); +} diff --git a/data-structures/src/main/java/com/baeldung/lrucache/Node.java b/data-structures/src/main/java/com/baeldung/lrucache/Node.java new file mode 100644 index 0000000000..340bb1dd82 --- /dev/null +++ b/data-structures/src/main/java/com/baeldung/lrucache/Node.java @@ -0,0 +1,71 @@ +package com.baeldung.lrucache; + +/** + * Created by arash on 09.07.21. + */ +public class Node implements LinkedListNode { + private T value; + private DoublyLinkedList list; + private LinkedListNode next; + private LinkedListNode prev; + + public Node(T value, LinkedListNode next, DoublyLinkedList list) { + this.value = value; + this.next = next; + this.setPrev(next.getPrev()); + this.prev.setNext(this); + this.next.setPrev(this); + this.list = list; + } + + @Override + public boolean hasElement() { + return true; + } + + @Override + public boolean isEmpty() { + return false; + } + + public T getElement() { + return value; + } + + public void detach() { + this.prev.setNext(this.getNext()); + this.next.setPrev(this.getPrev()); + } + + @Override + public DoublyLinkedList getListReference() { + return this.list; + } + + @Override + public LinkedListNode setPrev(LinkedListNode prev) { + this.prev = prev; + return this; + } + + @Override + public LinkedListNode setNext(LinkedListNode next) { + this.next = next; + return this; + } + + @Override + public LinkedListNode getPrev() { + return this.prev; + } + + @Override + public LinkedListNode getNext() { + return this.next; + } + + @Override + public LinkedListNode search(T value) { + return this.getElement() == value ? this : this.getNext().search(value); + } +} diff --git a/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java b/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java new file mode 100644 index 0000000000..f6e236342c --- /dev/null +++ b/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java @@ -0,0 +1,59 @@ +package com.baeldung.lrucache; + +import com.baeldung.lrucache.Cache; +import com.baeldung.lrucache.LRUCache; +import org.hamcrest.core.AllOf; +import org.junit.Before; +import org.junit.Test; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.IntStream; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class LRUCacheUnitTest { + + @Test + public void addSomeDataToCache_WhenGetData_ThenIsEqualWithCacheElement() { + LRUCache lruCache = new LRUCache<>(3); + lruCache.put("1", "test1"); + lruCache.put("2", "test2"); + lruCache.put("3", "test3"); + assertEquals(lruCache.get("1").get(), "test1"); + assertEquals(lruCache.get("2").get(), "test2"); + assertEquals(lruCache.get("3").get(), "test3"); + } + + @Test + public void addDataToCacheToTheNumberOfSize_WhenAddOneMoreData_ThenLeastRecentlyDataWillEvict() { + LRUCache lruCache = new LRUCache<>(3); + lruCache.put("1", "test1"); + lruCache.put("2", "test2"); + lruCache.put("3", "test3"); + lruCache.put("4", "test4"); + assertEquals(lruCache.get("1").isPresent(), false); + } + + @Test + public void runMultiThreadTask_WhenPutDataInConcurrentToCache_ThenNoDataLost() throws Exception { + final int size = 50; + final ExecutorService executorService = Executors.newFixedThreadPool(5); + Cache cache = new LRUCache<>(size); + CountDownLatch countDownLatch = new CountDownLatch(size); + try { + IntStream.range(0, size).mapToObj(key -> () -> { + cache.put(key, "value" + key); + System.out.println(Thread.currentThread().getName() + " " + key); + countDownLatch.countDown(); + }).forEach(executorService::submit); + countDownLatch.await(); + } finally { + executorService.shutdown(); + } + assertEquals(cache.size(), size); + IntStream.range(0, size).forEach(i -> assertEquals(cache.get(i).get(), "value" + i)); + } +} From d387500d53ab4250c791a7e592c9ea1082a34685 Mon Sep 17 00:00:00 2001 From: Remy Ohajinwa Date: Sun, 18 Jul 2021 04:41:05 -0500 Subject: [PATCH 085/114] BAEL-5013 Convert String to Camel Case (#10947) * BAEL-5004 Fixed overflow issues for Large numbers * BAEL-5013 Test cases * BAEL-5013 Convert to String solutions * BAEL-5013 convert to camel case using regex * BAEL-5004 Fixed overflow issues for Large numbers * BAEL-5013 Convert to Camel Case using Regex * BAEL-5013 Review changes * BAEL5013 cleanup * BAEL5013 review changes * BAEL5013 continuation index to 2 spaces * BAEL-5013 fixed test failure * BAEL-5013 Review changes Co-authored-by: Remy Ohajinwa --- .../core-java-string-conversions-2/pom.xml | 32 +++++ .../stringtocamelcase/StringToCamelCase.java | 109 +++++++++++++++++ .../StringToCamelCaseUnitTest.java | 111 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 core-java-modules/core-java-string-conversions-2/src/main/java/com/baeldung/stringtocamelcase/StringToCamelCase.java create mode 100644 core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtocamelcase/StringToCamelCaseUnitTest.java diff --git a/core-java-modules/core-java-string-conversions-2/pom.xml b/core-java-modules/core-java-string-conversions-2/pom.xml index 8a222a6b5d..584c808f56 100644 --- a/core-java-modules/core-java-string-conversions-2/pom.xml +++ b/core-java-modules/core-java-string-conversions-2/pom.xml @@ -33,7 +33,39 @@ ${hamcrest.version} test + + + com.ibm.icu + icu4j + ${icu.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.apache.commons + commons-text + ${commons-text.version} + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + 64.2 + 3.12.2 + 1.9 + 30.1.1-jre + core-java-string-conversions-2 diff --git a/core-java-modules/core-java-string-conversions-2/src/main/java/com/baeldung/stringtocamelcase/StringToCamelCase.java b/core-java-modules/core-java-string-conversions-2/src/main/java/com/baeldung/stringtocamelcase/StringToCamelCase.java new file mode 100644 index 0000000000..7a4369ac4a --- /dev/null +++ b/core-java-modules/core-java-string-conversions-2/src/main/java/com/baeldung/stringtocamelcase/StringToCamelCase.java @@ -0,0 +1,109 @@ +package com.baeldung.stringtocamelcase; + +import com.google.common.base.CaseFormat; +import com.ibm.icu.lang.UCharacter; +import com.ibm.icu.text.BreakIterator; +import org.apache.commons.text.CaseUtils; +import org.apache.commons.text.WordUtils; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class StringToCamelCase { + + public static String toCamelCaseByIteration(String text, char delimiter) { + if (text == null || text.isEmpty()) { + return text; + } + boolean shouldConvertNextCharToLower = true; + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char currentChar = text.charAt(i); + if (currentChar == delimiter) { + shouldConvertNextCharToLower = false; + } else if (shouldConvertNextCharToLower) { + builder.append(Character.toLowerCase(currentChar)); + } else { + builder.append(Character.toUpperCase(currentChar)); + shouldConvertNextCharToLower = true; + } + } + return builder.toString(); + } + + public static String toCamelCaseBySplitting(String text, String delimiter) { + if (text == null || text.isEmpty()) { + return text; + } + String[] words = text.split(delimiter); + StringBuilder builder = new StringBuilder(); + for (int i = 0, wordsLength = words.length; i < wordsLength; i++) { + String word = words[i]; + if (i == 0) { + //Make the first word all lowercase + word = word.isEmpty() ? word : word.toLowerCase(); + } else { + //Convert the first character to Uppercase and others to lowercase + // e.g sTRING =====> String + word = word.isEmpty() ? word : Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase(); + } + builder.append(word); + } + return builder.toString(); + } + + public static String toCamelCaseBySplittingUsingStreams(String text, String delimiter) { + if (text == null || text.isEmpty()) { + return text; + } + String[] words = text.split(delimiter); + //Convert the first word to lowercase and then every + //other word to Title Case. + String firstWord = words[0].toLowerCase(); + String otherWords = Arrays.stream(words, 1, words.length) + .filter(word -> !word.isEmpty()) + .map(word -> Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase()) + .collect(Collectors.joining("")); + + return firstWord + otherWords; + } + + public static String toCamelCaseByRegex(String text) { + StringBuilder builder = new StringBuilder(); + String[] words = text.split("[\\W_]+"); + for (int i = 0; i < words.length; i++) { + String word = words[i]; + if (i == 0) { + word = word.isEmpty() ? word : word.toLowerCase(); + } else { + word = word.isEmpty() ? word : Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase(); + } + builder.append(word); + } + return builder.toString(); + } + + //Third-Party Libraries + public static String toCamelCaseUsingICU4J(String text, String delimiter) { + if (text == null || text.isEmpty()) { + return text; + } + text = UCharacter.toTitleCase(text, BreakIterator.getTitleInstance()).replaceAll(delimiter, ""); + StringBuilder builder = new StringBuilder(text); + builder.setCharAt(0, Character.toLowerCase(text.charAt(0))); + return builder.toString(); + } + + public static String toCamelCaseUsingGuava(String text, String delimiter) { + String toUpperUnderscore = text.toUpperCase().replaceAll(delimiter, "_"); + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, toUpperUnderscore); + } + + public static String toCamelCaseUsingApacheCommons(String text, char delimiter) { + text = WordUtils.capitalizeFully(text, delimiter).replaceAll(String.valueOf(delimiter), ""); + StringBuilder builder = new StringBuilder(text); + builder.setCharAt(0, Character.toLowerCase(text.charAt(0))); + return builder.toString(); + } + +} diff --git a/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtocamelcase/StringToCamelCaseUnitTest.java b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtocamelcase/StringToCamelCaseUnitTest.java new file mode 100644 index 0000000000..3adc4434a9 --- /dev/null +++ b/core-java-modules/core-java-string-conversions-2/src/test/java/com/baeldung/stringtocamelcase/StringToCamelCaseUnitTest.java @@ -0,0 +1,111 @@ +package com.baeldung.stringtocamelcase; + + +import com.google.common.base.CaseFormat; +import org.apache.commons.text.CaseUtils; +import org.junit.Test; + +import static com.baeldung.stringtocamelcase.StringToCamelCase.*; +import static org.assertj.core.api.Assertions.*; + + +public class StringToCamelCaseUnitTest { + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseByIteration_ThenReturnCamelCase() { + assertThat(toCamelCaseByIteration("THIS STRING SHOULD BE IN CAMEL CASE", ' ')).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseByIteration_ThenReturnCamelCase() { + assertThat(toCamelCaseByIteration("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", '_')).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseBySplitting_ThenReturnCamelCase() { + assertThat(toCamelCaseBySplitting("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseBySplitting_ThenReturnCamelCase() { + assertThat(toCamelCaseBySplitting("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseBySplittingUsingStreams_ThenReturnCamelCase() { + assertThat(toCamelCaseBySplittingUsingStreams("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseBySplittingUsingStreams_ThenReturnCamelCase() { + assertThat(toCamelCaseBySplittingUsingStreams("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingApacheCommonsText_ThenReturnCamelCase() { + assertThat(CaseUtils.toCamelCase("THIS STRING SHOULD BE IN CAMEL CASE", false, ' ')) + .isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseUsingApacheCommonsText_ThenReturnCamelCase() { + assertThat(CaseUtils.toCamelCase("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", false, '_')) + .isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingICU4J_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingICU4J("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseUsingICU4J_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingICU4J("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingGuava_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingGuava("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseUsingGuava_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingGuava("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingApacheCommons_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingApacheCommons("THIS STRING SHOULD BE IN CAMEL CASE", ' ')).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithUnderscores_WhenToCamelCaseUsingApacheCommons_ThenReturnCamelCase() { + assertThat(toCamelCaseUsingApacheCommons("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", '_')).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteSpaces_WhenToCamelCaseByRegex_ThenReturnCamelCase() { + assertThat(toCamelCaseByRegex("THIS STRING SHOULD BE IN CAMEL CASE")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenStringWithWhiteUnderscores_WhenToCamelCaseByRegex_ThenReturnCamelCase() { + assertThat(toCamelCaseByRegex("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE")).isEqualTo("thisStringShouldBeInCamelCase"); + } + + @Test + public void givenRandomString_WhenToCamelCaseByRegex_ThenReturnCamelCase() { + assertThat(toCamelCaseByRegex("Please Turn this56738 to camel Case")).isEqualTo("pleaseTurnThis56738ToCamelCase"); + } + + @Test + public void givenRandomStringWithDifferentDelimiters_WhenToCamelCaseByRegex_ThenReturnCamelCase() { + assertThat(toCamelCaseByRegex("Please Turn this56738 to camel Case This should-be_in;camel-case")).isEqualTo("pleaseTurnThis56738ToCamelCaseThisShouldBeInCamelCase"); + } + + @Test + public void givenUppercaseWordWithUnderscores_WhenCaseFormatToLowerCamel_ThenReturnCamelCase() { + assertThat(CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "THIS_STRING_SHOULD_BE_IN_CAMEL_CASE")).isEqualTo("thisStringShouldBeInCamelCase"); + } + +} From d2035e86af363171b8bc2e0629a6a7e3dd7be00c Mon Sep 17 00:00:00 2001 From: psevestre Date: Sun, 18 Jul 2021 12:19:13 -0300 Subject: [PATCH 086/114] [BAEL-5014] Kubernetes Admission Controller (#11044) * [BAEL-4849] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code --- .../k8s-admission-controller/Dockerfile | 11 + kubernetes/k8s-admission-controller/pom.xml | 86 ++++++ .../kubernetes/admission/Application.java | 17 ++ .../config/AdmissionControllerProperties.java | 22 ++ .../controller/AdmissionReviewController.java | 30 ++ .../admission/dto/AdmissionReviewData.java | 31 ++ .../dto/AdmissionReviewException.java | 28 ++ .../dto/AdmissionReviewResponse.java | 25 ++ .../admission/dto/AdmissionStatus.java | 13 + .../admission/service/AdmissionService.java | 218 ++++++++++++++ .../service/AdmissionServiceUnitTest.java | 65 ++++ .../src/test/k8s/nginx.yaml | 23 ++ .../src/test/resources/test1.json | 84 ++++++ .../src/test/resources/test2.json | 85 ++++++ .../src/test/resources/test3.json | 94 ++++++ .../src/test/resources/test4.json | 48 +++ .../src/test/terraform/.gitignore | 3 + .../src/test/terraform/.terraform.lock.hcl | 57 ++++ .../src/test/terraform/component.auto.tfvars | 10 + .../src/test/terraform/main.tf | 277 ++++++++++++++++++ .../src/test/terraform/providers.tf | 14 + .../src/test/terraform/variables.tf | 50 ++++ kubernetes/pom.xml | 8 +- 23 files changed, 1295 insertions(+), 4 deletions(-) create mode 100644 kubernetes/k8s-admission-controller/Dockerfile create mode 100644 kubernetes/k8s-admission-controller/pom.xml create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/Application.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewData.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewResponse.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionStatus.java create mode 100644 kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/service/AdmissionService.java create mode 100644 kubernetes/k8s-admission-controller/src/test/java/com/baeldung/kubernetes/admission/service/AdmissionServiceUnitTest.java create mode 100644 kubernetes/k8s-admission-controller/src/test/k8s/nginx.yaml create mode 100644 kubernetes/k8s-admission-controller/src/test/resources/test1.json create mode 100644 kubernetes/k8s-admission-controller/src/test/resources/test2.json create mode 100644 kubernetes/k8s-admission-controller/src/test/resources/test3.json create mode 100644 kubernetes/k8s-admission-controller/src/test/resources/test4.json create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/.gitignore create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/.terraform.lock.hcl create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/component.auto.tfvars create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/main.tf create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/providers.tf create mode 100644 kubernetes/k8s-admission-controller/src/test/terraform/variables.tf diff --git a/kubernetes/k8s-admission-controller/Dockerfile b/kubernetes/k8s-admission-controller/Dockerfile new file mode 100644 index 0000000000..f8939ee7c8 --- /dev/null +++ b/kubernetes/k8s-admission-controller/Dockerfile @@ -0,0 +1,11 @@ +FROM adoptopenjdk:11-jre-hotspot as builder +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} application.jar +RUN java -Djarmode=layertools -jar application.jar extract + +FROM adoptopenjdk:11-jre-hotspot +COPY --from=builder dependencies/ ./ +COPY --from=builder snapshot-dependencies/ ./ +COPY --from=builder spring-boot-loader/ ./ +COPY --from=builder application/ ./ +ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/pom.xml b/kubernetes/k8s-admission-controller/pom.xml new file mode 100644 index 0000000000..fbee9ceba6 --- /dev/null +++ b/kubernetes/k8s-admission-controller/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ./../../parent-boot-2 + + + k8s-admission-controller + k8s-admission-controller + Demo project for Spring Boot + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.projectreactor + reactor-test + test + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-devtools + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + org.projectlombok + lombok + + + com.baeldung.kubernetes.admission.Application + + true + + + + + + + diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/Application.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/Application.java new file mode 100644 index 0000000000..1260ec0af9 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/Application.java @@ -0,0 +1,17 @@ +package com.baeldung.kubernetes.admission; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +import com.baeldung.kubernetes.admission.config.AdmissionControllerProperties; + +@SpringBootApplication +@EnableConfigurationProperties(AdmissionControllerProperties.class) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java new file mode 100644 index 0000000000..2352068ba1 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java @@ -0,0 +1,22 @@ +/** + * + */ +package com.baeldung.kubernetes.admission.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Data; + +/** + * @author lighthouse.psevestre + * + */ +@ConfigurationProperties(prefix = "admission-controller") +@Data +public class AdmissionControllerProperties { + + private boolean disabled; + private String annotation = "com.baeldung/wait-for-it"; + private String waitForItImage = "willwill/wait-for-it"; + +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java new file mode 100644 index 0000000000..a73aa3d89b --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java @@ -0,0 +1,30 @@ +/** + * + */ +package com.baeldung.kubernetes.admission.controller; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.kubernetes.admission.dto.AdmissionReviewResponse; +import com.baeldung.kubernetes.admission.service.AdmissionService; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import lombok.RequiredArgsConstructor; +import reactor.core.publisher.Mono; + +/** + * + */ +@RestController +@RequiredArgsConstructor +public class AdmissionReviewController { + + private final AdmissionService admissionService; + + @PostMapping(path = "/mutate") + public Mono processAdmissionReviewRequest(@RequestBody Mono request) { + return request.map((body) -> admissionService.processAdmission(body)); + } +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewData.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewData.java new file mode 100644 index 0000000000..6d590ff408 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewData.java @@ -0,0 +1,31 @@ +/** + * + */ +package com.baeldung.kubernetes.admission.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +import lombok.Builder; +import lombok.Data; + +/** + * Result sent to the API server after reviewing and, possibly + * modifying the incoming request + */ +@Builder +@Data +public class AdmissionReviewData { + + final String uid; + final boolean allowed; + + @JsonInclude(Include.NON_NULL) + final String patchType; + + @JsonInclude(Include.NON_NULL) + final String patch; + + @JsonInclude(Include.NON_NULL) + final AdmissionStatus status; +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java new file mode 100644 index 0000000000..a788eca461 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java @@ -0,0 +1,28 @@ +package com.baeldung.kubernetes.admission.dto; + +/** + * Exceção utilizada para reportar erros de validação no manifesto recebido para admissão + * @author lighthouse.psevestre + * + */ +public class AdmissionReviewException extends RuntimeException { + + private static final long serialVersionUID = 1L; + private final int code; + + public AdmissionReviewException(int code, String message) { + super(message); + this.code = code; + } + + public AdmissionReviewException(String message) { + super(message); + this.code = 400; + + } + + public int getCode() { + return code; + } + +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewResponse.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewResponse.java new file mode 100644 index 0000000000..1780f52540 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewResponse.java @@ -0,0 +1,25 @@ +/** + * + */ +package com.baeldung.kubernetes.admission.dto; + +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; + +/** + * Response "envelope" sent back to the API Server + */ +@Builder +@Data +public class AdmissionReviewResponse { + + @Default + final String apiVersion = "admission.k8s.io/v1"; + + @Default + final String kind = "AdmissionReview"; + + final AdmissionReviewData response; + +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionStatus.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionStatus.java new file mode 100644 index 0000000000..ccab7ac958 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionStatus.java @@ -0,0 +1,13 @@ +package com.baeldung.kubernetes.admission.dto; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class AdmissionStatus { + + int code; + String message; + +} diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/service/AdmissionService.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/service/AdmissionService.java new file mode 100644 index 0000000000..814bafbae7 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/service/AdmissionService.java @@ -0,0 +1,218 @@ +/** + * + */ +package com.baeldung.kubernetes.admission.service; + +import java.util.Base64; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.baeldung.kubernetes.admission.config.AdmissionControllerProperties; +import com.baeldung.kubernetes.admission.dto.AdmissionReviewData; +import com.baeldung.kubernetes.admission.dto.AdmissionReviewException; +import com.baeldung.kubernetes.admission.dto.AdmissionReviewResponse; +import com.baeldung.kubernetes.admission.dto.AdmissionStatus; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * Process an incoming admission request and add the "wait-for-it" init container + * if there's an appropriate annotation + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class AdmissionService { + + private final AdmissionControllerProperties admissionControllerProperties; + private final ObjectMapper om; + + public AdmissionReviewResponse processAdmission(ObjectNode body) { + + String uid = body.path("request") + .required("uid") + .asText(); + + log.info("[I42] processAdmission: uid={}",uid); + if ( log.isDebugEnabled()) { + log.debug("processAdmission: body={}", body.toPrettyString()); + } + + // Get request annotations + JsonNode annotations = body.path("request") + .path("object") + .path("metadata") + .path("annotations"); + log.info("processAdmision: annotations={}", annotations.toString()); + + AdmissionReviewData data; + try { + if (admissionControllerProperties.isDisabled()) { + log.info("[I58] 'disabled' option in effect. No changes to current request will be made"); + data = createSimpleAllowedReview(body); + } else if (annotations.isMissingNode()) { + log.info("[I68] No annotations found in request. No changes will be made"); + data = createSimpleAllowedReview(body); + } else { + data = processAnnotations(body, annotations); + } + + log.info("[I65] Review result: isAllowed=" + data.isAllowed()); + log.info("[I64] AdmissionReviewData= {}", data); + + return AdmissionReviewResponse.builder() + .apiVersion(body.required("apiVersion").asText()) + .kind(body.required("kind").asText()) + .response(data) + .build(); + } catch (AdmissionReviewException ex) { + log.error("[E72] Error processing AdmissionRequest: code={}, message={}", ex.getCode(), ex.getMessage()); + data = createRejectedAdmissionReview(body, ex.getCode(), ex.getMessage()); + + return AdmissionReviewResponse.builder() + .apiVersion(body.required("apiVersion").asText()) + .kind(body.required("kind").asText()) + .response(data) + .build(); + } catch (Exception ex) { + log.error("[E72] Unable to process AdmissionRequest: " + ex.getMessage(), ex); + data = createRejectedAdmissionReview(body, 500, ex.getMessage()); + return AdmissionReviewResponse.builder() + .apiVersion(body.required("apiVersion").asText()) + .kind(body.required("kind").asText()) + .response(data) + .build(); + } + } + + /** + * @param body + * @return + */ + protected AdmissionReviewData createSimpleAllowedReview(ObjectNode body) { + AdmissionReviewData data; + String requestId = body.path("request") + .required("uid") + .asText(); + + data = AdmissionReviewData.builder() + .allowed(true) + .uid(requestId) + .build(); + + return data; + + } + + /** + * @param body + * @return + */ + protected AdmissionReviewData createRejectedAdmissionReview(ObjectNode body, int code, String message) { + AdmissionReviewData data; + String requestId = body.path("request") + .required("uid") + .asText(); + + AdmissionStatus status = AdmissionStatus.builder() + .code(code) + .message(message) + .build(); + + data = AdmissionReviewData.builder() + .allowed(false) + .uid(requestId) + .status(status) + .build(); + + return data; + + } + + /** + * Processa anotações incluídas no deployment + * @param annotations + * @return + */ + protected AdmissionReviewData processAnnotations(ObjectNode body, JsonNode annotations) { + + if (annotations.path(admissionControllerProperties.getAnnotation()) + .isMissingNode()) { + log.info("[I78] processAnnotations: Annotation {} not found in deployment deployment.", admissionControllerProperties.getAnnotation()); + return createSimpleAllowedReview(body); + } + else { + log.info("[I163] annotation found: {}", annotations.path(admissionControllerProperties.getAnnotation())); + } + + // Get wait-for-it arguments from the annotation + String waitForArgs = annotations.path(admissionControllerProperties.getAnnotation()) + .asText(); + + log.info("[I169] waitForArgs={}", waitForArgs); + // Create a PATCH object + String patch = injectInitContainer(body, waitForArgs); + + return AdmissionReviewData.builder() + .allowed(true) + .uid(body.path("request") + .required("uid") + .asText()) + .patch(Base64.getEncoder() + .encodeToString(patch.getBytes())) + .patchType("JSONPatch") + .build(); + + } + + /** + * Creates the JSONPatch to be included in the admission response + * @param body + * @param waitForArgs + * @return JSONPatch string + */ + protected String injectInitContainer(ObjectNode body, String waitForArgs) { + + // Recover original init containers from the request + JsonNode originalSpec = body.path("request") + .path("object") + .path("spec") + .path("template") + .path("spec") + .require(); + + JsonNode maybeInitContainers = originalSpec.path("initContainers"); + ArrayNode initContainers = + maybeInitContainers.isMissingNode()? + om.createArrayNode():(ArrayNode) maybeInitContainers; + + // Create the patch array + ArrayNode patchArray = om.createArrayNode(); + ObjectNode addNode = patchArray.addObject(); + + addNode.put("op", "add"); + addNode.put("path", "/spec/template/spec/initContainers"); + ArrayNode values = addNode.putArray("value"); + + // Preserve original init containers + values.addAll(initContainers); + + // append the "wait-for-it" container + ObjectNode wfi = values.addObject(); + wfi.put("name", "wait-for-it-" + UUID.randomUUID()); // Create an unique name, JIC + wfi.put("image", admissionControllerProperties.getWaitForItImage()); + + ArrayNode args = wfi.putArray("args"); + for (String s : waitForArgs.split("\\s")) { + args.add(s); + } + + return patchArray.toString(); + } +} diff --git a/kubernetes/k8s-admission-controller/src/test/java/com/baeldung/kubernetes/admission/service/AdmissionServiceUnitTest.java b/kubernetes/k8s-admission-controller/src/test/java/com/baeldung/kubernetes/admission/service/AdmissionServiceUnitTest.java new file mode 100644 index 0000000000..544b48a9d4 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/java/com/baeldung/kubernetes/admission/service/AdmissionServiceUnitTest.java @@ -0,0 +1,65 @@ +package com.baeldung.kubernetes.admission.service; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Base64; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.kubernetes.admission.config.AdmissionControllerProperties; +import com.baeldung.kubernetes.admission.dto.AdmissionReviewResponse; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +@SpringBootTest +@ActiveProfiles("test") +@EnableConfigurationProperties(AdmissionControllerProperties.class) +class AdmissionServiceUnitTest { + + @Autowired + private ObjectMapper mapper; + + @Autowired + private AdmissionService admissionService; + + @Test + void whenAnnotationPresent_thenAddContainer() throws Exception { + + InputStream is = this.getClass() + .getClassLoader() + .getResourceAsStream("test1.json"); + JsonNode body = mapper.readTree(is); + AdmissionReviewResponse response = admissionService.processAdmission((ObjectNode) body); + assertNotNull(response); + assertNotNull(response.getResponse()); + assertNotNull(response.getResponse()); + assertTrue(response.getResponse() + .isAllowed()); + + String jsonResponse = mapper.writeValueAsString(response); + System.out.println(jsonResponse); + + // Decode Patch data + String b64patch = response.getResponse() + .getPatch(); + assertNotNull(b64patch); + byte[] patch = Base64.getDecoder() + .decode(b64patch); + + JsonNode root = mapper.reader() + .readTree(new ByteArrayInputStream(patch)); + assertTrue(root instanceof ArrayNode); + + assertEquals(1, ((ArrayNode) root).size()); + + } + +} diff --git a/kubernetes/k8s-admission-controller/src/test/k8s/nginx.yaml b/kubernetes/k8s-admission-controller/src/test/k8s/nginx.yaml new file mode 100644 index 0000000000..0c601660d1 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/k8s/nginx.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend + labels: + app: nginx + annotations: + com.baeldung/wait-for-it: "www.google.com:80" +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/kubernetes/k8s-admission-controller/src/test/resources/test1.json b/kubernetes/k8s-admission-controller/src/test/resources/test1.json new file mode 100644 index 0000000000..0ad42ae133 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/resources/test1.json @@ -0,0 +1,84 @@ +{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "request": { + "uid": "c46a6607-129d-425b-af2f-c6f87a0756da", + "kind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "resource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "requestKind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "requestResource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "name": "test-deployment", + "namespace": "test-namespace", + "operation": "CREATE", + "object": { + "kind": "Deployment", + "apiVersion": "apps/v1", + "metadata": { + "name": "test-deployment", + "namespace": "test-namespace", + "annotations": { + "com.baeldung/wait-for-it": "www.google.com:80" + } + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app": "test-app" + } + }, + "template": { + "metadata": { + "name": "test-app", + "creationTimestamp": null, + "labels": { + "app": "test-app" + } + }, + "spec": { + "containers": [ + { + "name": "app", + "image": "test-app-image:latest", + "ports": [ + { + "name": "http", + "containerPort": 8080, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always" + } + ] + } + } + }, + "status": {} + }, + "oldObject": null, + "dryRun": false, + "options": { + "kind": "CreateOptions", + "apiVersion": "meta.k8s.io/v1" + } + } +} \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/src/test/resources/test2.json b/kubernetes/k8s-admission-controller/src/test/resources/test2.json new file mode 100644 index 0000000000..5b8a6ca243 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/resources/test2.json @@ -0,0 +1,85 @@ +{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "request": { + "uid": "c46a6607-129d-425b-af2f-c6f87a0756da", + "kind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "resource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "requestKind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "requestResource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "name": "test-deployment", + "namespace": "test-namespace", + "operation": "CREATE", + "object": { + "kind": "Deployment", + "apiVersion": "apps/v1", + "metadata": { + "name": "test-deployment", + "namespace": "test-namespace", + "annotations": { + "com.baeldung/wait-for-it": "www.google.com:80" + } + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app": "test-app" + } + }, + "template": { + "metadata": { + "name": "test-app", + "creationTimestamp": null, + "labels": { + "app": "test-app" + } + }, + "spec": { + "initContainers": [], + "containers": [ + { + "name": "app", + "image": "test-app-image:latest", + "ports": [ + { + "name": "http", + "containerPort": 8080, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always" + } + ] + } + } + }, + "status": {} + }, + "oldObject": null, + "dryRun": false, + "options": { + "kind": "CreateOptions", + "apiVersion": "meta.k8s.io/v1" + } + } +} \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/src/test/resources/test3.json b/kubernetes/k8s-admission-controller/src/test/resources/test3.json new file mode 100644 index 0000000000..9cb4d516f9 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/resources/test3.json @@ -0,0 +1,94 @@ +{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "request": { + "uid": "c46a6607-129d-425b-af2f-c6f87a0756da", + "kind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "resource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "requestKind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "requestResource": { + "group": "apps", + "version": "v1", + "resource": "deployments" + }, + "name": "test-deployment", + "namespace": "test-namespace", + "operation": "CREATE", + "object": { + "kind": "Deployment", + "apiVersion": "apps/v1", + "metadata": { + "name": "test-deployment", + "namespace": "test-namespace", + "annotations": { + "com.baeldung/wait-for-it": "www.google.com:80" + } + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app": "test-app" + } + }, + "template": { + "metadata": { + "name": "test-app", + "creationTimestamp": null, + "labels": { + "app": "test-app" + } + }, + "spec": { + "initContainers": [ + { + "name": "init1", + "image": "test-app-image:latest", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always" + } + ], + "containers": [ + { + "name": "app", + "image": "test-app-image:latest", + "ports": [ + { + "name": "http", + "containerPort": 8080, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always" + } + ] + } + } + }, + "status": {} + }, + "oldObject": null, + "dryRun": false, + "options": { + "kind": "CreateOptions", + "apiVersion": "meta.k8s.io/v1" + } + } +} \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/src/test/resources/test4.json b/kubernetes/k8s-admission-controller/src/test/resources/test4.json new file mode 100644 index 0000000000..1e3be90a93 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/resources/test4.json @@ -0,0 +1,48 @@ +{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "request": { + "uid": "26beb334-739a-48d2-b04d-25f6e5e7c106", + "kind": { + "group": "apps", + "version": "v1", + "kind": "Deployment" + }, + "resource": {}, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } +} \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/.gitignore b/kubernetes/k8s-admission-controller/src/test/terraform/.gitignore new file mode 100644 index 0000000000..4c305a080a --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/.gitignore @@ -0,0 +1,3 @@ +.terraform +terraform.tfstate +terraform.tfstate.backup diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/.terraform.lock.hcl b/kubernetes/k8s-admission-controller/src/test/terraform/.terraform.lock.hcl new file mode 100644 index 0000000000..e13c37b4ec --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/.terraform.lock.hcl @@ -0,0 +1,57 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "2.3.2" + constraints = "2.3.2" + hashes = [ + "h1:D8HWX3vouTPI3Jicq43xOQyoYWtSsVua92cBVrJ3ZMs=", + "zh:10f71c170be13538374a4b9553fcb3d98a6036bcd1ca5901877773116c3f828e", + "zh:11d2230e531b7480317e988207a73cb67b332f225b0892304983b19b6014ebe0", + "zh:3317387a9a6cc27fd7536b8f3cad4b8a9285e9461f125c5a15d192cef3281856", + "zh:458a9858362900fbe97e00432ae8a5bef212a4dacf97a57ede7534c164730da4", + "zh:50ea297007d9fe53e5411577f87a4b13f3877ce732089b42f938430e6aadff0d", + "zh:56705c959e4cbea3b115782d04c62c68ac75128c5c44ee7aa4043df253ffbfe3", + "zh:7eb3722f7f036e224824470c3e0d941f1f268fcd5fa2f8203e0eee425d0e1484", + "zh:9f408a6df4d74089e6ce18f9206b06b8107ddb57e2bc9b958a6b7dc352c62980", + "zh:aadd25ccc3021040808feb2645779962f638766eb583f586806e59f24dde81bb", + "zh:b101c3456e4309b09aab129b0118561178c92cb4be5d96dec553189c3084dca1", + "zh:ec08478573b4953764099fbfd670fae81dc24b60e467fb3b023e6fab50b70a9e", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.1.0" + hashes = [ + "h1:SFT7X3zY18CLWjoH2GfQyapxsRv6GDKsy9cF1aRwncc=", + "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", + "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", + "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", + "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", + "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", + "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", + "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", + "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", + "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", + "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", + "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + ] +} + +provider "registry.terraform.io/hashicorp/tls" { + version = "3.1.0" + hashes = [ + "h1:ekOxs6MjdIElt8h9crEVaOwWbEqtfUUfArtA13Jkk6A=", + "zh:3d46616b41fea215566f4a957b6d3a1aa43f1f75c26776d72a98bdba79439db6", + "zh:623a203817a6dafa86f1b4141b645159e07ec418c82fe40acd4d2a27543cbaa2", + "zh:668217e78b210a6572e7b0ecb4134a6781cc4d738f4f5d09eb756085b082592e", + "zh:95354df03710691773c8f50a32e31fca25f124b7f3d6078265fdf3c4e1384dca", + "zh:9f97ab190380430d57392303e3f36f4f7835c74ea83276baa98d6b9a997c3698", + "zh:a16f0bab665f8d933e95ca055b9c8d5707f1a0dd8c8ecca6c13091f40dc1e99d", + "zh:be274d5008c24dc0d6540c19e22dbb31ee6bfdd0b2cddd4d97f3cd8a8d657841", + "zh:d5faa9dce0a5fc9d26b2463cea5be35f8586ab75030e7fa4d4920cd73ee26989", + "zh:e9b672210b7fb410780e7b429975adcc76dd557738ecc7c890ea18942eb321a5", + "zh:eb1f8368573d2370605d6dbf60f9aaa5b64e55741d96b5fb026dbfe91de67c0d", + "zh:fc1e12b713837b85daf6c3bb703d7795eaf1c5177aebae1afcf811dd7009f4b0", + ] +} diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/component.auto.tfvars b/kubernetes/k8s-admission-controller/src/test/terraform/component.auto.tfvars new file mode 100644 index 0000000000..eb1cdaea53 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/component.auto.tfvars @@ -0,0 +1,10 @@ +# +# Sample variable values. +# +namespace="default" +deployment_name="wait-for-it-admission-controller" +replicas=1 +image="psevestre/wait-for-it-admission-controller" +image_prefix="" +image_version="latest" +k8s_config_context="minikube" diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/main.tf b/kubernetes/k8s-admission-controller/src/test/terraform/main.tf new file mode 100644 index 0000000000..a0717c4013 --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/main.tf @@ -0,0 +1,277 @@ + +locals { + prefix = var.image_prefix != "" ? "${var.image_prefix}/":"" + image = "${local.prefix}${var.image}:${var.image_version}" + cloud_sdk_image = "${local.prefix}frapsoft/openssl" + ns = data.kubernetes_namespace.ns.metadata[0].name + + # Spring SSL Configuration + webhook_config_json = jsonencode({ + server = { + port = 443 + ssl = { + "key-store" = "/shared-config/webhook.p12" + "key-store-type" = "PKCS12" + "key-alias" = "webhook" + "key-store-password" = "" + } + } + + admission-controller = { + disabled = false + image-prefix = "gcr.io/sandboxbv-01" + } + }) + +} + + +# Resource namespace +data "kubernetes_namespace" "ns" { + metadata { + name = var.namespace + } +} + +# TLS Key +resource "tls_private_key" "tls" { + algorithm = "RSA" +} + +# CSR +resource "tls_cert_request" "tls" { + key_algorithm = "RSA" + private_key_pem = tls_private_key.tls.private_key_pem + subject { + common_name = "${var.deployment_name}.${var.namespace}.svc" + } + + dns_names = [ + var.deployment_name, + "${var.deployment_name}.${var.namespace}", + "${var.deployment_name}.${var.namespace}.svc", + "${var.deployment_name}.${var.namespace}.svc.cluster.local" + ] + +} + +# HTTPS Certificate +resource "tls_self_signed_cert" "tls" { + key_algorithm = tls_private_key.tls.algorithm + private_key_pem = tls_private_key.tls.private_key_pem + + subject { + common_name = "${var.deployment_name}.${local.ns}" + } + + validity_period_hours = 24*365*20 + + dns_names = [ + var.deployment_name, + "${var.deployment_name}.${var.namespace}", + "${var.deployment_name}.${var.namespace}.svc", + "${var.deployment_name}.${var.namespace}.svc.cluster.local" + ] + + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth" + ] +} + +# Certificado +# Obs: Desativado pois o certificado fica preso no estado "Issued" +resource "kubernetes_certificate_signing_request" "tls" { + count = 0 + metadata { + name = "${var.deployment_name}.${var.namespace}" + } + + auto_approve = true + + spec { + usages = [ + "key encipherment", + "digital signature", + "server auth" + ] + + signer_name = "kubernetes.io/kubelet-serving" + + request = tls_cert_request.tls.cert_request_pem + } + +} + +# Secret to store TLS key/cert +resource "kubernetes_secret" "tls" { + metadata { + namespace = local.ns + name = var.deployment_name + } + + data = { + "webhook-key.pem" = tls_private_key.tls.private_key_pem + "webhook-cert.pem" = tls_self_signed_cert.tls.cert_pem + } + +} + +# Deployment +resource "kubernetes_deployment" "main" { + metadata { + name = var.deployment_name + namespace = local.ns + } + + spec { + replicas = var.replicas + selector { + match_labels = { + app = var.deployment_name + } + } + + template { + metadata { + labels = { + app = var.deployment_name + } + } + + spec { + container { + image = local.image + name = var.deployment_name + volume_mount { + mount_path = "/shared-config" + name = "shared-config" + } + + env { + name = "SPRING_APPLICATION_JSON" + value = local.webhook_config_json + } + + } + + init_container { + name = "setup-keystore" + image = local.cloud_sdk_image + + args = [ + "pkcs12", "-export", + "-in", "/secret/webhook-cert.pem", + "-inkey", "/secret/webhook-key.pem", + "-name", "webhook", + "-out", "/shared-config/webhook.p12", + "-passout", "pass:" + ] + + volume_mount { + mount_path = "/shared-config" + name = "shared-config" + } + + volume_mount { + mount_path = "/secret/webhook-cert.pem" + name = "webhook-secret" + sub_path = "webhook-cert.pem" + } + + volume_mount { + mount_path = "/secret/webhook-key.pem" + name = "webhook-secret" + sub_path = "webhook-key.pem" + } + + } + + volume { + name = "shared-config" + empty_dir {} + } + + volume { + name = "webhook-secret" + secret { + secret_name = kubernetes_secret.tls.metadata[0].name + items { + key = "webhook-cert.pem" + path = "webhook-cert.pem" + } + items { + key = "webhook-key.pem" + path = "webhook-key.pem" + } + } + } + + } + } + } +} + +# Service +resource "kubernetes_service" "svc" { + metadata { + name = var.deployment_name + namespace = local.ns + } + + spec { + selector = { + "app" = var.deployment_name + } + + port { + name = "https" + port = 443 + protocol = "TCP" + target_port = 443 + } + + type = "ClusterIP" + } +} + +# Admission Controller +resource "kubernetes_mutating_webhook_configuration" "waitforit" { + metadata { + name = var.deployment_name + } + + webhook { + name = var.admission_controller_name + admission_review_versions = [ "v1", "v1beta1" ] + + #failure_policy = "Ignore" # + + client_config { + + service { + name = kubernetes_service.svc.metadata[0].name + namespace = local.ns + path = "/mutate" + port = 443 + } + + # IMPORTANT: CA_BUNDLE must be Base64-encoded + ca_bundle = tls_self_signed_cert.tls.cert_pem + } + + rule { + api_groups = [ "*" ] + api_versions = [ "*" ] + operations = [ "CREATE", "UPDATE" ] + resources = [ "deployments", "statefulsets" ] + } + + side_effects = "None" # + } + + depends_on = [ + kubernetes_deployment.main + ] +} diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/providers.tf b/kubernetes/k8s-admission-controller/src/test/terraform/providers.tf new file mode 100644 index 0000000000..eb095caa0e --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.3.2" + } + } +} + +# Use standard kubectl environment to get connection details +provider "kubernetes" { + config_context = var.k8s_config_context + config_path = var.k8s_config_path +} \ No newline at end of file diff --git a/kubernetes/k8s-admission-controller/src/test/terraform/variables.tf b/kubernetes/k8s-admission-controller/src/test/terraform/variables.tf new file mode 100644 index 0000000000..33ca735f0d --- /dev/null +++ b/kubernetes/k8s-admission-controller/src/test/terraform/variables.tf @@ -0,0 +1,50 @@ +variable "namespace" { + type = string + description = "Namespace where the Admission Controller will be deploymed" +} + +variable "deployment_name" { + type = string + description = "Admission Controller Deployment Name" +} + +variable "replicas" { + type = number + description = "Number of replicas used in the deployment" + default = 3 +} + +variable "image" { + type = string + description = "Admission Controller image name" +} + +variable "image_version" { + type = string + description = "Admission Controller image version name" + default = "latest" +} + +variable "image_prefix" { + type = string + description = "Image repository prefix" + default = "gcr.io/baeldung" +} + +variable "admission_controller_name" { + type = string + description = "Admission Controller name" + default = "wait-for-it.service.local" +} + +variable "k8s_config_context" { + type = string + description = "Name of the K8S config context" +} + +variable "k8s_config_path" { + type = string + description = "Location of the standard K8S configuration" + default = "~/.kube/config" + +} \ No newline at end of file diff --git a/kubernetes/pom.xml b/kubernetes/pom.xml index 72cb1577a4..57ae4fd596 100644 --- a/kubernetes/pom.xml +++ b/kubernetes/pom.xml @@ -1,6 +1,5 @@ - + + 4.0.0 kubernetes pom @@ -13,5 +12,6 @@ k8s-intro - + k8s-admission-controller + \ No newline at end of file From 81fddd7bc32ab1841e422a7bb92eb94aae83e598 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Sun, 18 Jul 2021 20:13:45 +0430 Subject: [PATCH 087/114] BAEL-4233: Why doesn't a missing annotation cause a ClassNotFoundException at runtime? (#11024) --- .../main/java/com/baeldung/missingannotation/A.java | 8 ++++++++ .../main/java/com/baeldung/missingannotation/B.java | 10 ++++++++++ .../main/java/com/baeldung/missingannotation/C.java | 9 +++++++++ .../main/java/com/baeldung/missingannotation/D.java | 4 ++++ 4 files changed, 31 insertions(+) create mode 100644 core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/A.java create mode 100644 core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/B.java create mode 100644 core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/C.java create mode 100644 core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/D.java diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/A.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/A.java new file mode 100644 index 0000000000..daf9f60b96 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/A.java @@ -0,0 +1,8 @@ +package com.baeldung.missingannotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface A { +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/B.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/B.java new file mode 100644 index 0000000000..a86b2f72ec --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/B.java @@ -0,0 +1,10 @@ +package com.baeldung.missingannotation; + +@A +@C(D.class) +public class B { + + public static void main(String[] args) { + System.out.println("It worked"); + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/C.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/C.java new file mode 100644 index 0000000000..2adf2b42fa --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/C.java @@ -0,0 +1,9 @@ +package com.baeldung.missingannotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface C { + Class value(); +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/D.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/D.java new file mode 100644 index 0000000000..7c534fa682 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/missingannotation/D.java @@ -0,0 +1,4 @@ +package com.baeldung.missingannotation; + +public class D { +} From 4524fbf9e36b94713ad6834cb95f802414cc5ef8 Mon Sep 17 00:00:00 2001 From: Ahwin Oghenerukevwe <32289710+ahwinemman@users.noreply.github.com> Date: Mon, 19 Jul 2021 06:31:25 +0100 Subject: [PATCH 088/114] BAEL-4143: sample usages of @SuppressWarnings warning names (#11021) Co-authored-by: oahwin --- .../ClassWithSuppressWarningsNames.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java new file mode 100644 index 0000000000..aad7cf49eb --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java @@ -0,0 +1,46 @@ +package com.baeldung.annotations; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings({"serial", "unchecked"}) +public class ClassWithSuppressWarningsNames implements Serializable { + +// private static final long serialVersionUID = -1166032307853492833L; + + @SuppressWarnings("unused") + public static void suppressBoxingWarning() { + int value = 5; + int unusedVar = 10; // no warning here + List list = new ArrayList<>(); + list.add(Integer.valueOf(value)); + } + + @SuppressWarnings("deprecated") + void suppressDeprecatedWarning() { + ClassWithSuppressWarningsNames cls = new ClassWithSuppressWarningsNames(); + cls.deprecatedMethod(); // no warning here + } + + @SuppressWarnings("fallthrough") + String suppressFallthroughWarning() { + int day = 5; + switch (day) { + case 5: + return "This is day 5"; +// break; // no warning here + case 10: + return "This is day 10"; +// break; + default: + return "This default day"; + } + } + + @Deprecated + String deprecatedMethod() { + return "deprecated method"; + } + +} From b9571f02f5f3a9933ea41a16f5ba98a044254035 Mon Sep 17 00:00:00 2001 From: psevestre Date: Mon, 19 Jul 2021 23:41:58 -0300 Subject: [PATCH 089/114] [BAEL-5014] Kubernetes Admission Controller (#11055) * [BAEL-4849] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code * [BAEL-4968] Remove extra comments --- .../admission/config/AdmissionControllerProperties.java | 4 ---- .../admission/controller/AdmissionReviewController.java | 3 --- .../kubernetes/admission/dto/AdmissionReviewException.java | 5 ----- 3 files changed, 12 deletions(-) diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java index 2352068ba1..f9103d85ba 100644 --- a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/config/AdmissionControllerProperties.java @@ -7,10 +7,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import lombok.Data; -/** - * @author lighthouse.psevestre - * - */ @ConfigurationProperties(prefix = "admission-controller") @Data public class AdmissionControllerProperties { diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java index a73aa3d89b..21434535f9 100644 --- a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/controller/AdmissionReviewController.java @@ -14,9 +14,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.RequiredArgsConstructor; import reactor.core.publisher.Mono; -/** - * - */ @RestController @RequiredArgsConstructor public class AdmissionReviewController { diff --git a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java index a788eca461..07a3fa5b7a 100644 --- a/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java +++ b/kubernetes/k8s-admission-controller/src/main/java/com/baeldung/kubernetes/admission/dto/AdmissionReviewException.java @@ -1,10 +1,5 @@ package com.baeldung.kubernetes.admission.dto; -/** - * Exceção utilizada para reportar erros de validação no manifesto recebido para admissão - * @author lighthouse.psevestre - * - */ public class AdmissionReviewException extends RuntimeException { private static final long serialVersionUID = 1L; From 66b40ed662f87fc8ddf68ee1cb0c2585c9ae1a3c Mon Sep 17 00:00:00 2001 From: Arash Ariani Date: Tue, 20 Jul 2021 09:51:36 +0430 Subject: [PATCH 090/114] Bael 4464 (#11041) * BAEL-4464 : how to implement LRU-Cache in java codes added * BAEL-4464 : how to implement LRU-Cache in java codes added - package named fixed * BAEL-4464 : how to implement LRU-Cache in java codes added - package named changed * BAEL-4464 : how to implement LRU-Cache in java codes added - unitTest fixed * BAEL-4464 : issues 4,5 fixed. * fixed some issues in BAEL-4464 --- .../baeldung/lrucache/DoublyLinkedList.java | 49 +++++++++---------- .../java/com/baeldung/lrucache/LRUCache.java | 29 +++++------ 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java b/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java index a2b56741a2..5850d6c13d 100644 --- a/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java +++ b/data-structures/src/main/java/com/baeldung/lrucache/DoublyLinkedList.java @@ -10,67 +10,62 @@ public class DoublyLinkedList { private LinkedListNode head; private LinkedListNode tail; private AtomicInteger size; - private ReentrantReadWriteLock.ReadLock readLock; - private ReentrantReadWriteLock.WriteLock writeLock; - - + private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + public DoublyLinkedList() { this.dummyNode = new DummyNode(this); - ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - readLock = lock.readLock(); - writeLock = lock.writeLock(); clear(); } public void clear() { - writeLock.lock(); + this.lock.writeLock().lock(); try { head = dummyNode; tail = dummyNode; size = new AtomicInteger(0); } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } public int size() { - readLock.lock(); + this.lock.readLock().lock(); try { return size.get(); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } public boolean isEmpty() { - readLock.lock(); + this.lock.readLock().lock(); try { return head.isEmpty(); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } public boolean contains(T value) { - readLock.lock(); + this.lock.readLock().lock(); try { return search(value).hasElement(); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } public LinkedListNode search(T value) { - readLock.lock(); + this.lock.readLock().lock(); try { return head.search(value); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } public LinkedListNode add(T value) { - writeLock.lock(); + this.lock.writeLock().lock(); try { head = new Node(value, head, this); if (tail.isEmpty()) { @@ -79,12 +74,12 @@ public class DoublyLinkedList { size.incrementAndGet(); return head; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } public boolean addAll(Collection values) { - writeLock.lock(); + this.lock.writeLock().lock(); try { for (T value : values) { if (add(value).isEmpty()) { @@ -93,12 +88,12 @@ public class DoublyLinkedList { } return true; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } public LinkedListNode remove(T value) { - writeLock.lock(); + this.lock.writeLock().lock(); try { LinkedListNode linkedListNode = head.search(value); if (!linkedListNode.isEmpty()) { @@ -113,12 +108,12 @@ public class DoublyLinkedList { } return linkedListNode; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } public LinkedListNode removeTail() { - writeLock.lock(); + this.lock.writeLock().lock(); try { LinkedListNode oldTail = tail; if (oldTail == head) { @@ -132,7 +127,7 @@ public class DoublyLinkedList { } return oldTail; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } @@ -141,7 +136,7 @@ public class DoublyLinkedList { } public LinkedListNode updateAndMoveToFront(LinkedListNode node, T newValue) { - writeLock.lock(); + this.lock.writeLock().lock(); try { if (node.isEmpty() || (this != (node.getListReference()))) { return dummyNode; @@ -150,7 +145,7 @@ public class DoublyLinkedList { add(newValue); return head; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } diff --git a/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java b/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java index 0128cadf78..3032a90d8e 100644 --- a/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java +++ b/data-structures/src/main/java/com/baeldung/lrucache/LRUCache.java @@ -1,6 +1,5 @@ package com.baeldung.lrucache; -import java.util.Hashtable; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -10,21 +9,17 @@ public class LRUCache implements Cache { private int size; private Map>> linkedListNodeMap; private DoublyLinkedList> doublyLinkedList; - private ReentrantReadWriteLock.ReadLock readLock; - private ReentrantReadWriteLock.WriteLock writeLock; + private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public LRUCache(int size) { this.size = size; - this.linkedListNodeMap = new Hashtable<>(size); + this.linkedListNodeMap = new ConcurrentHashMap<>(size); this.doublyLinkedList = new DoublyLinkedList<>(); - ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - this.readLock = lock.readLock(); - this.writeLock = lock.writeLock(); } @Override public boolean put(K key, V value) { - writeLock.lock(); + this.lock.writeLock().lock(); try { CacheElement item = new CacheElement(key, value); LinkedListNode> newNode; @@ -43,13 +38,13 @@ public class LRUCache implements Cache { this.linkedListNodeMap.put(key, newNode); return true; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } @Override public Optional get(K key) { - readLock.lock(); + this.lock.readLock().lock(); try { LinkedListNode> linkedListNode = this.linkedListNodeMap.get(key); if (linkedListNode != null && !linkedListNode.isEmpty()) { @@ -58,17 +53,17 @@ public class LRUCache implements Cache { } return Optional.empty(); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } @Override public int size() { - readLock.lock(); + this.lock.readLock().lock(); try { return doublyLinkedList.size(); } finally { - readLock.unlock(); + this.lock.readLock().unlock(); } } @@ -79,18 +74,18 @@ public class LRUCache implements Cache { @Override public void clear() { - writeLock.lock(); + this.lock.writeLock().lock(); try { linkedListNodeMap.clear(); doublyLinkedList.clear(); } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } private boolean evictElement() { - writeLock.lock(); + this.lock.writeLock().lock(); try { LinkedListNode> linkedListNode = doublyLinkedList.removeTail(); if (linkedListNode.isEmpty()) { @@ -99,7 +94,7 @@ public class LRUCache implements Cache { linkedListNodeMap.remove(linkedListNode.getElement().getKey()); return true; } finally { - writeLock.unlock(); + this.lock.writeLock().unlock(); } } } From b848bfead36d50ef13f8cbec3558f4a76f520357 Mon Sep 17 00:00:00 2001 From: Kai Yuan Date: Wed, 21 Jul 2021 05:17:19 +0200 Subject: [PATCH 091/114] add Phaser implementations (#11051) --- .../ThreadsStartAtSameTime.java | 27 +++++++++++++++++++ .../WorkerWithPhaser.java | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithPhaser.java diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java index 72363aeb82..3e90bd4399 100644 --- a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/ThreadsStartAtSameTime.java @@ -3,6 +3,7 @@ package com.baeldung.threadsstartatsametime; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Phaser; public class ThreadsStartAtSameTime { @@ -12,6 +13,11 @@ public class ThreadsStartAtSameTime { Thread.sleep(30); usingCyclicBarrier(); + + Thread.sleep(30); + + usingPhaser(); + } private static void usingCountDownLatch() throws InterruptedException { @@ -56,4 +62,25 @@ public class ThreadsStartAtSameTime { barrier.await(); } + private static void usingPhaser() throws InterruptedException { + System.out.println("\n==============================================="); + System.out.println(" >>> Using Phaser <<<"); + System.out.println("==============================================="); + + Phaser phaser = new Phaser(); + phaser.register(); + + WorkerWithPhaser worker1 = new WorkerWithPhaser("Worker with phaser 1", phaser); + WorkerWithPhaser worker2 = new WorkerWithPhaser("Worker with phaser 2", phaser); + + worker1.start(); + worker2.start(); + + Thread.sleep(10);//simulation of some actual work + + System.out.println("-----------------------------------------------"); + System.out.println(" Now open the phaser barrier:"); + System.out.println("-----------------------------------------------"); + phaser.arriveAndAwaitAdvance(); + } } diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithPhaser.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithPhaser.java new file mode 100644 index 0000000000..44994d1cd0 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/threadsstartatsametime/WorkerWithPhaser.java @@ -0,0 +1,26 @@ +package com.baeldung.threadsstartatsametime; + +import java.time.Instant; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Phaser; + +public class WorkerWithPhaser extends Thread { + private Phaser phaser; + + public WorkerWithPhaser(String name, Phaser phaser) { + this.phaser = phaser; + phaser.register(); + setName(name); + } + + @Override public void run() { + try { + System.out.printf("[ %s ] created, blocked by the phaser\n", getName()); + phaser.arriveAndAwaitAdvance(); + System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now()); + // do actual work here... + } catch (IllegalStateException e) { + e.printStackTrace(); + } + } +} From d85e3aff2d6823f3960ddc831e9d69c4a1e955f8 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:16:53 +0800 Subject: [PATCH 092/114] Update README.md --- java-numbers-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-numbers-4/README.md b/java-numbers-4/README.md index cdd53692e0..f053a82b80 100644 --- a/java-numbers-4/README.md +++ b/java-numbers-4/README.md @@ -3,3 +3,4 @@ - [Probability in Java](https://www.baeldung.com/java-probability) - [Understanding the & 0xff Value in Java](https://www.baeldung.com/java-and-0xff) - [Determine if an Integer’s Square Root Is an Integer in Java](https://www.baeldung.com/java-find-if-square-root-is-integer) +- [Guide to Java BigInteger](https://www.baeldung.com/java-biginteger) From a28a32fdc99acfb298169e0b66c6460cf688f0ee Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:19:36 +0800 Subject: [PATCH 093/114] Update README.md --- spring-boot-modules/spring-boot-logging-log4j2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-boot-logging-log4j2/README.md b/spring-boot-modules/spring-boot-logging-log4j2/README.md index aa6bb9b6e1..9688f8f83c 100644 --- a/spring-boot-modules/spring-boot-logging-log4j2/README.md +++ b/spring-boot-modules/spring-boot-logging-log4j2/README.md @@ -6,3 +6,4 @@ This module contains articles about logging in Spring Boot projects with Log4j 2 - [Logging in Spring Boot](https://www.baeldung.com/spring-boot-logging) - [Logging to Graylog with Spring Boot](https://www.baeldung.com/graylog-with-spring-boot) - [Log Groups in Spring Boot 2.1](https://www.baeldung.com/spring-boot-log-groups) +- [Writing Log Data to Syslog Using Log4j2](https://www.baeldung.com/log4j-to-syslog) From a038d871825d2bc503f95fdc8f9d68b5a06216e4 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:22:46 +0800 Subject: [PATCH 094/114] Create README.md --- maven-modules/plugin-management/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 maven-modules/plugin-management/README.md diff --git a/maven-modules/plugin-management/README.md b/maven-modules/plugin-management/README.md new file mode 100644 index 0000000000..dec3a71cfd --- /dev/null +++ b/maven-modules/plugin-management/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Plugin Management in Maven](https://www.baeldung.com/maven-plugin-management) From b32513fdb4e543d79cc778b7907877cce1eab1d5 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:26:08 +0800 Subject: [PATCH 095/114] Create README.md --- guava-modules/guava-concurrency/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 guava-modules/guava-concurrency/README.md diff --git a/guava-modules/guava-concurrency/README.md b/guava-modules/guava-concurrency/README.md new file mode 100644 index 0000000000..12fca9a1a5 --- /dev/null +++ b/guava-modules/guava-concurrency/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Guava’s Futures and ListenableFuture](https://www.baeldung.com/guava-futures-listenablefuture) From 9709c690e21536da65e505896621a1c06572ed14 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:28:15 +0800 Subject: [PATCH 096/114] Update README.md --- core-java-modules/core-java-string-conversions-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-conversions-2/README.md b/core-java-modules/core-java-string-conversions-2/README.md index 229a40f91f..46eb783a27 100644 --- a/core-java-modules/core-java-string-conversions-2/README.md +++ b/core-java-modules/core-java-string-conversions-2/README.md @@ -8,4 +8,5 @@ This module contains articles about string conversions from/to another type. - [Convert Character Array to String in Java](https://www.baeldung.com/java-char-array-to-string) - [Converting String to BigDecimal in Java](https://www.baeldung.com/java-string-to-bigdecimal) - [Converting String to BigInteger in Java](https://www.baeldung.com/java-string-to-biginteger) +- [Convert a String to Camel Case](https://www.baeldung.com/java-string-to-camel-case) - More articles: [[<-- prev]](/core-java-string-conversions) From ddb8d5202c2bcefd72f6f0c8c16dfce737ce5f7c Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:30:44 +0800 Subject: [PATCH 097/114] Update README.md --- core-java-modules/core-java-annotations/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-annotations/README.md b/core-java-modules/core-java-annotations/README.md index 93da3aea62..f5815ab61a 100644 --- a/core-java-modules/core-java-annotations/README.md +++ b/core-java-modules/core-java-annotations/README.md @@ -10,3 +10,4 @@ - [Overview of Java Built-in Annotations](https://www.baeldung.com/java-default-annotations) - [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation) - [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency) +- [Why Missing Annotations Don’t Cause ClassNotFoundException](https://www.baeldung.com/classnotfoundexception-missing-annotation) From 16571f28c0b289028812a886144bce9bb21756a5 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:32:41 +0800 Subject: [PATCH 098/114] Update README.md --- core-java-modules/core-java-annotations/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-annotations/README.md b/core-java-modules/core-java-annotations/README.md index f5815ab61a..18f5589771 100644 --- a/core-java-modules/core-java-annotations/README.md +++ b/core-java-modules/core-java-annotations/README.md @@ -11,3 +11,4 @@ - [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation) - [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency) - [Why Missing Annotations Don’t Cause ClassNotFoundException](https://www.baeldung.com/classnotfoundexception-missing-annotation) +- [Valid @SuppressWarnings Warning Names](https://www.baeldung.com/java-suppresswarnings-valid-names) From 9fb3c09fd8d90714c5843e98c4b26d364960c09c Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 22 Jul 2021 01:35:37 +0800 Subject: [PATCH 099/114] Update README.md --- rabbitmq/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rabbitmq/README.md b/rabbitmq/README.md index 1420998f66..7fea2e85a0 100644 --- a/rabbitmq/README.md +++ b/rabbitmq/README.md @@ -5,4 +5,5 @@ This module contains articles about RabbitMQ. ### Relevant articles - [Introduction to RabbitMQ](https://www.baeldung.com/rabbitmq) - [Exchanges, Queues, and Bindings in RabbitMQ](https://www.baeldung.com/java-rabbitmq-exchanges-queues-bindings) +- [Pub-Sub vs. Message Queues](https://www.baeldung.com/pub-sub-vs-message-queues) From dd4902e8daf2554e6408c7defe48085f4f0c516c Mon Sep 17 00:00:00 2001 From: Karthick Sridhar Date: Wed, 7 Jul 2021 23:32:00 +0530 Subject: [PATCH 100/114] [BAEL-4478] IP address is in given range or not using java --- .../core-java-networking-3/pom.xml | 21 +++++ .../ipingivenrange/IPWithGivenRangeCheck.java | 81 +++++++++++++++++++ .../IPWithGivenRangeCheckUnitTest.java | 58 +++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 core-java-modules/core-java-networking-3/src/main/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheck.java create mode 100644 core-java-modules/core-java-networking-3/src/test/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheckUnitTest.java diff --git a/core-java-modules/core-java-networking-3/pom.xml b/core-java-modules/core-java-networking-3/pom.xml index 0ad800e173..d3b2398b75 100644 --- a/core-java-modules/core-java-networking-3/pom.xml +++ b/core-java-modules/core-java-networking-3/pom.xml @@ -47,6 +47,24 @@ javax.mail 1.6.2 + + + com.github.seancfoley + ipaddress + ${seancfoley.ipaddress.version} + + + + com.github.jgonian + commons-ip-math + ${jgonian.commons-ip-math.version} + + + + com.googlecode.java-ipv6 + java-ipv6 + ${googlecode.ipv6.version} + @@ -66,6 +84,9 @@ 9.4.31.v20200723 10.0.0-M7 3.11.1 + 5.3.3 + 1.32 + 0.17 \ No newline at end of file diff --git a/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheck.java b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheck.java new file mode 100644 index 0000000000..634c88ccba --- /dev/null +++ b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheck.java @@ -0,0 +1,81 @@ +package com.baeldung.ipingivenrange; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import inet.ipaddr.IPAddress; +import inet.ipaddr.IPAddressSeqRange; +import inet.ipaddr.IPAddressString; +import inet.ipaddr.AddressStringException; + +import com.github.jgonian.ipmath.Ipv4; +import com.github.jgonian.ipmath.Ipv4Range; +import com.github.jgonian.ipmath.Ipv6; +import com.github.jgonian.ipmath.Ipv6Range; +import com.googlecode.ipv6.IPv6Address; +import com.googlecode.ipv6.IPv6AddressRange; + +public class IPWithGivenRangeCheck { + + // using IPAddress library + public static boolean checkIPIsInGivenRange(String inputIP, String rangeStartIP, String rangeEndIP) throws AddressStringException { + IPAddress startIPAddress = new IPAddressString(rangeStartIP).getAddress(); + IPAddress endIPAddress = new IPAddressString(rangeEndIP).getAddress(); + IPAddressSeqRange ipRange = startIPAddress.toSequentialRange(endIPAddress); + IPAddress inputIPAddress = new IPAddressString(inputIP).toAddress(); + + return ipRange.contains(inputIPAddress); + } + + // using Commons IP Math library for IPv4 + public static boolean checkIPv4IsInRange(String inputIP, String rangeStartIP, String rangeEndIP) { + Ipv4 startIPAddress = Ipv4.of(rangeStartIP); + Ipv4 endIPAddress = Ipv4.of(rangeEndIP); + Ipv4Range ipRange = Ipv4Range.from(startIPAddress) + .to(endIPAddress); + Ipv4 inputIPAddress = Ipv4.of(inputIP); + + return ipRange.contains(inputIPAddress); + } + + // using Commons IP Math library for IPv6 + public static boolean checkIPv6IsInRange(String inputIP, String rangeStartIP, String rangeEndIP) { + Ipv6 startIPAddress = Ipv6.of(rangeStartIP); + Ipv6 endIPAddress = Ipv6.of(rangeEndIP); + Ipv6Range ipRange = Ipv6Range.from(startIPAddress) + .to(endIPAddress); + Ipv6 inputIPAddress = Ipv6.of(inputIP); + + return ipRange.contains(inputIPAddress); + } + + // checking IP is in range by converting it to an integer + public static boolean checkIPv4IsInRangeByConvertingToInt(String inputIP, String rangeStartIP, String rangeEndIP) throws UnknownHostException { + long startIPAddress = ipToLongInt(InetAddress.getByName(rangeStartIP)); + long endIPAddress = ipToLongInt(InetAddress.getByName(rangeEndIP)); + long inputIPAddress = ipToLongInt(InetAddress.getByName(inputIP)); + + return (inputIPAddress >= startIPAddress && inputIPAddress <= endIPAddress); + } + + private static long ipToLongInt(InetAddress ipAddress) { + long resultIP = 0; + byte[] ipAddressOctets = ipAddress.getAddress(); + + for (byte octet : ipAddressOctets) { + resultIP <<= 8; + resultIP |= octet & 0xFF; + } + return resultIP; + } + + // using Java IPv6 library (which internally uses two long integers to store ip address) + public static boolean checkIPv6IsInRangeByIPv6library(String inputIP, String rangeStartIP, String rangeEndIP) { + IPv6Address startIPAddress = IPv6Address.fromString(rangeStartIP); + IPv6Address endIPAddress = IPv6Address.fromString(rangeEndIP); + IPv6AddressRange ipRange = IPv6AddressRange.fromFirstAndLast(startIPAddress, endIPAddress); + IPv6Address inputIPAddress = IPv6Address.fromString(inputIP); + + return ipRange.contains(inputIPAddress); + } +} diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheckUnitTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheckUnitTest.java new file mode 100644 index 0000000000..a9b54834d5 --- /dev/null +++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/ipingivenrange/IPWithGivenRangeCheckUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.ipingivenrange; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import com.baeldung.ipingivenrange.IPWithGivenRangeCheck; + +class IPWithGivenRangeCheckUnitTest { + + @Test + void givenIPv4Addresses_whenIsInRange_thenReturnsTrue() throws Exception { + // test for IPAddress library + assertTrue(IPWithGivenRangeCheck.checkIPIsInGivenRange("192.220.3.0", "192.210.0.0", "192.255.0.0")); + + // test for Common IP Math library + assertTrue(IPWithGivenRangeCheck.checkIPv4IsInRange("192.220.3.0", "192.210.0.0", "192.255.0.0")); + + // test for IPv4 by converting it to an integer and checking if it falls under the specified range. + assertTrue(IPWithGivenRangeCheck.checkIPv4IsInRangeByConvertingToInt("192.220.3.0", "192.210.0.0", "192.255.0.0")); + } + + @Test + void givenIPv4Addresses_whenIsNotInRange_thenReturnsFalse() throws Exception { + // test for IPAddress library + assertFalse(IPWithGivenRangeCheck.checkIPIsInGivenRange("192.200.0.0", "192.210.0.0", "192.255.0.0")); + + // test for Common IP Math library + assertFalse(IPWithGivenRangeCheck.checkIPv4IsInRange("192.200.0.0", "192.210.0.0", "192.255.0.0")); + + // test for IPv4 by converting it to an integer and checking if it falls under the specified range. + assertFalse(IPWithGivenRangeCheck.checkIPv4IsInRangeByConvertingToInt("192.200.0.0", "192.210.0.0", "192.255.0.0")); + } + + @Test + void givenIPv6Addresses_whenIsInRange_thenReturnsTrue() throws Exception { + // test for IPAddress library + assertTrue(IPWithGivenRangeCheck.checkIPIsInGivenRange("2001:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334")); + + // test for Common IP Math library + assertTrue(IPWithGivenRangeCheck.checkIPv6IsInRange("2001:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334")); + + // test for Java IPv6 library + assertTrue(IPWithGivenRangeCheck.checkIPv6IsInRangeByIPv6library("fe80::226:2dff:fefa:dcba", "fe80::226:2dff:fefa:cd1f", "fe80::226:2dff:fefa:ffff")); + } + + @Test + void givenIPv6Addresses_whenIsNotInRange_thenReturnsFalse() throws Exception { + // test for IPAddress library + assertFalse(IPWithGivenRangeCheck.checkIPIsInGivenRange("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334")); + + // test for Common IP Math library + assertFalse(IPWithGivenRangeCheck.checkIPv6IsInRange("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334")); + + // test for Java IPv6 library + assertFalse(IPWithGivenRangeCheck.checkIPv6IsInRangeByIPv6library("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334")); + } +} From b39c550ff6b3e92149f432b8138db3dc4b2491f2 Mon Sep 17 00:00:00 2001 From: makapszenna <66560584+makapszenna@users.noreply.github.com> Date: Fri, 23 Jul 2021 12:13:16 +0200 Subject: [PATCH 101/114] BAEL-4977 CQL Data Types (#11017) Co-authored-by: Adrianna Zychewicz --- .../src/main/resources/data_types.cql | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 persistence-modules/java-cassandra/src/main/resources/data_types.cql diff --git a/persistence-modules/java-cassandra/src/main/resources/data_types.cql b/persistence-modules/java-cassandra/src/main/resources/data_types.cql new file mode 100644 index 0000000000..67e6fb4634 --- /dev/null +++ b/persistence-modules/java-cassandra/src/main/resources/data_types.cql @@ -0,0 +1,75 @@ +CREATE + KEYSPACE baeldung + WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1}; +USE baeldung; + +CREATE TABLE numeric_types +( + type1 int PRIMARY KEY, + type2 bigint, + type3 smallint, + type4 tinyint, + type5 varint, + type6 float, + type7 double, + type8 decimal +); + +CREATE TABLE text_types +( + primaryKey int PRIMARY KEY, + type2 text, + type3 varchar, + type4 ascii +); + +CREATE TABLE date_types +( + primaryKey int PRIMARY KEY, + type1 timestamp, + type2 time, + type3 date, + type4 timeuuid, + type5 duration +); + +CREATE TABLE other_types +( + primaryKey int PRIMARY KEY, + type1 boolean, + type2 uuid, + type3 blob, + type4 inet +); + +CREATE TABLE counter_type +( + primaryKey uuid PRIMARY KEY, + type1 counter +); + +CREATE TABLE collection_types +( + primaryKey int PRIMARY KEY, + email set +); + +ALTER TABLE collection_types + ADD scores list; + +ALTER TABLE collection_types + ADD address map; + +CREATE TABLE tuple_type +( + primaryKey int PRIMARY KEY, + type1 tuple +); + +CREATE TYPE user_defined_type ( type1 timestamp, type2 text, type3 text, type4 text); + +CREATE TABLE user_type +( + primaryKey int PRIMARY KEY, + our_type user_defined_type +); From 0ed3f460154d633540e219792c1502d23881d324 Mon Sep 17 00:00:00 2001 From: Arash Ariani Date: Fri, 23 Jul 2021 17:18:28 +0430 Subject: [PATCH 102/114] Bael 4464 (#11062) * BAEL-4464 : how to implement LRU-Cache in java codes added * BAEL-4464 : how to implement LRU-Cache in java codes added - package named fixed * BAEL-4464 : how to implement LRU-Cache in java codes added - package named changed * BAEL-4464 : how to implement LRU-Cache in java codes added - unitTest fixed * BAEL-4464 : issues 4,5 fixed. * fixed some issues in BAEL-4464 * BAEL-4464 : some tips on unitTest fixed --- .../baeldung/lrucache/LRUCacheUnitTest.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java b/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java index f6e236342c..e64085ae4c 100644 --- a/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java +++ b/data-structures/src/test/java/com/baeldung/lrucache/LRUCacheUnitTest.java @@ -1,17 +1,10 @@ package com.baeldung.lrucache; -import com.baeldung.lrucache.Cache; -import com.baeldung.lrucache.LRUCache; -import org.hamcrest.core.AllOf; -import org.junit.Before; import org.junit.Test; -import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.IntStream; - -import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; public class LRUCacheUnitTest { @@ -22,9 +15,9 @@ public class LRUCacheUnitTest { lruCache.put("1", "test1"); lruCache.put("2", "test2"); lruCache.put("3", "test3"); - assertEquals(lruCache.get("1").get(), "test1"); - assertEquals(lruCache.get("2").get(), "test2"); - assertEquals(lruCache.get("3").get(), "test3"); + assertEquals("test1", lruCache.get("1").get()); + assertEquals("test2", lruCache.get("2").get()); + assertEquals("test3", lruCache.get("3").get()); } @Test @@ -34,7 +27,7 @@ public class LRUCacheUnitTest { lruCache.put("2", "test2"); lruCache.put("3", "test3"); lruCache.put("4", "test4"); - assertEquals(lruCache.get("1").isPresent(), false); + assertFalse(lruCache.get("1").isPresent()); } @Test @@ -46,7 +39,6 @@ public class LRUCacheUnitTest { try { IntStream.range(0, size).mapToObj(key -> () -> { cache.put(key, "value" + key); - System.out.println(Thread.currentThread().getName() + " " + key); countDownLatch.countDown(); }).forEach(executorService::submit); countDownLatch.await(); @@ -54,6 +46,6 @@ public class LRUCacheUnitTest { executorService.shutdown(); } assertEquals(cache.size(), size); - IntStream.range(0, size).forEach(i -> assertEquals(cache.get(i).get(), "value" + i)); + IntStream.range(0, size).forEach(i -> assertEquals("value" + i, cache.get(i).get())); } } From dd34c377daaf58d815a4cb1f256900587b94bed3 Mon Sep 17 00:00:00 2001 From: anmoldeep0123 Date: Sat, 24 Jul 2021 03:46:22 +0530 Subject: [PATCH 103/114] BAEL-4456 | Trusting a Self-Signed Cert in OkHTTP (#11065) * BAEL-4220 | A Guide to IllegalAccessError and when it happens * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | BDD test names * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4933 | Differences between static classes and the singleton pattern in Java * BAEL-4456 | Trusting a Self-Signed Cert in OkHTTP Co-authored-by: root --- .../test/java/com/baeldung/okhttp/Consts.java | 5 + .../ssl/OkHttpSSLSelfSignedCertLiveTest.java | 108 ++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 libraries-http-2/src/test/java/com/baeldung/okhttp/Consts.java create mode 100644 libraries-http-2/src/test/java/com/baeldung/okhttp/ssl/OkHttpSSLSelfSignedCertLiveTest.java diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/Consts.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/Consts.java new file mode 100644 index 0000000000..3e0c47f793 --- /dev/null +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/Consts.java @@ -0,0 +1,5 @@ +package com.baeldung.okhttp; + +public interface Consts { + int SSL_APPLICATION_PORT = 8443; +} \ No newline at end of file diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/ssl/OkHttpSSLSelfSignedCertLiveTest.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/ssl/OkHttpSSLSelfSignedCertLiveTest.java new file mode 100644 index 0000000000..3e7fad2a29 --- /dev/null +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/ssl/OkHttpSSLSelfSignedCertLiveTest.java @@ -0,0 +1,108 @@ +package com.baeldung.okhttp.ssl; + +import static com.baeldung.okhttp.Consts.SSL_APPLICATION_PORT; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.junit.Before; +import org.junit.Test; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +/** + * Execute spring-security-web-boot-2 module before running this live test + * @see com.baeldung.ssl.HttpsEnabledApplication + */ +public class OkHttpSSLSelfSignedCertLiveTest { + + private final String HTTPS_WELCOME_URL = "https://localhost:" + SSL_APPLICATION_PORT + "/welcome"; + + private OkHttpClient.Builder builder; + + @Before + public void init() { + builder = new OkHttpClient.Builder(); + } + + @Test(expected = SSLHandshakeException.class) + public void whenHTTPSSelfSignedCertGET_thenException() throws IOException { + builder.build() + .newCall(new Request.Builder().url(HTTPS_WELCOME_URL) + .build()) + .execute(); + } + + @Test(expected = SSLPeerUnverifiedException.class) + public void givenTrustAllCerts_whenHTTPSSelfSignedCertGET_thenException() throws GeneralSecurityException, IOException { + final TrustManager TRUST_ALL_CERTS = new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[] {}; + } + }; + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new TrustManager[] { TRUST_ALL_CERTS }, new java.security.SecureRandom()); + builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) TRUST_ALL_CERTS); + builder.build() + .newCall(new Request.Builder().url(HTTPS_WELCOME_URL) + .build()) + .execute(); + } + + @Test + public void givenTrustAllCertsSkipHostnameVerification_whenHTTPSSelfSignedCertGET_then200OK() throws GeneralSecurityException, IOException { + final TrustManager TRUST_ALL_CERTS = new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[] {}; + } + }; + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new TrustManager[] { TRUST_ALL_CERTS }, new java.security.SecureRandom()); + builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) TRUST_ALL_CERTS); + builder.hostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + Response response = builder.build() + .newCall(new Request.Builder().url(HTTPS_WELCOME_URL) + .build()) + .execute(); + assertEquals(200, response.code()); + assertNotNull(response.body()); + assertEquals("

Welcome to Secured Site

", response.body() + .string()); + } +} From 5a37927a90adb1fc079bfb14cd5b7f35e60154e3 Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Wed, 26 May 2021 23:39:55 +0530 Subject: [PATCH 104/114] Adding code for BAEL-4957 - Spring validation in the service layer --- spring-service-layer-validation/.gitignore | 63 +++++++++++++++ spring-service-layer-validation/README.md | 12 +++ spring-service-layer-validation/pom.xml | 46 +++++++++++ .../SpringServiceLayerValidationApp.java | 13 ++++ .../controller/UserAccountController.java | 22 ++++++ .../servicevalidation/dao/UserAccountDao.java | 32 ++++++++ .../servicevalidation/domain/UserAccount.java | 77 +++++++++++++++++++ .../servicevalidation/domain/UserAddress.java | 17 ++++ .../service/UserAccountService.java | 44 +++++++++++ 9 files changed, 326 insertions(+) create mode 100644 spring-service-layer-validation/.gitignore create mode 100644 spring-service-layer-validation/README.md create mode 100644 spring-service-layer-validation/pom.xml create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/.gitignore b/spring-service-layer-validation/.gitignore new file mode 100644 index 0000000000..8f5ee06047 --- /dev/null +++ b/spring-service-layer-validation/.gitignore @@ -0,0 +1,63 @@ +# Created by https://www.gitignore.io/api/eclipse + +### Eclipse ### + +.metadata +target/ +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Eclipse Patch ### +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# End of https://www.gitignore.io/api/eclipse \ No newline at end of file diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md new file mode 100644 index 0000000000..674831d6a5 --- /dev/null +++ b/spring-service-layer-validation/README.md @@ -0,0 +1,12 @@ +## Spring Boot MVC + +This module contains articles about validation in Service layer of Spring Boot project. + +### Relevant Articles: + +- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) +- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) +- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) +- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) +- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) +- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-service-layer-validation/pom.xml b/spring-service-layer-validation/pom.xml new file mode 100644 index 0000000000..31ec757699 --- /dev/null +++ b/spring-service-layer-validation/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + com.baeldung.spring-service-layer-validation + spring-service-layer-validation + 0.0.1-SNAPSHOT + + + UTF-8 + 12 + 12 + + + + org.springframework.boot + spring-boot-starter-parent + 2.4.5 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.hibernate.validator + hibernate-validator + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java new file mode 100644 index 0000000000..ea80a5da33 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.servicevalidation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringServiceLayerValidationApp { + + public static void main(String[] args) { + SpringApplication.run(SpringServiceLayerValidationApp.class, args); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java new file mode 100644 index 0000000000..b558ed89c2 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.servicevalidation.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; +import com.baeldung.spring.servicevalidation.service.UserAccountService; + +@RestController +public class UserAccountController { + + @Autowired + private UserAccountService service; + + @PostMapping("/addUserAccount") + public Object addUserAccount(@RequestBody UserAccount userAccount) { + return service.addUserAccount(userAccount); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java new file mode 100644 index 0000000000..d170ceef58 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.servicevalidation.dao; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountDao { + + private Map DB = new HashMap(); + + public String addUserAccount(UserAccount useraccount) { + DB.put(useraccount.getName(), useraccount); + return "success"; + } + + public Collection getAllUserAccounts() { + + Collection list = DB.values(); + if(list.isEmpty()) { + list.addAll(DB.values()); + } + return list; + + } + + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java new file mode 100644 index 0000000000..5b0e795a8a --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java @@ -0,0 +1,77 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class UserAccount { + + @NotNull(message = "Password must be between 4 to 15 characters") + @Size(min = 4, max = 15) + private String password; + + @NotBlank(message = "Name must not be blank") + private String name; + + @Min(value = 18, message = "Age should not be less than 18") + private int age; + + @NotBlank(message = "Phone must not be blank") + private String phone; + + @Valid + @NotNull(message = "UserAddress must not be blank") + private UserAddress useraddress; + + public UserAddress getUseraddress() { + return useraddress; + } + + public void setUseraddress(UserAddress useraddress) { + this.useraddress = useraddress; + } + + public UserAccount() { + + } + + public UserAccount(String email, String password, String name, int age) { + this.password = password; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java new file mode 100644 index 0000000000..85e7dfc05c --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.constraints.NotBlank; +public class UserAddress { + + @NotBlank + private String countryCode; + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java new file mode 100644 index 0000000000..9a376fda6b --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.servicevalidation.service; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.dao.UserAccountDao; +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountService { + + @Autowired + private Validator validator; + + @Autowired + private UserAccountDao dao; + + public String addUserAccount(UserAccount useraccount) { + + Set> violations = validator.validate(useraccount); + + if (!violations.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (ConstraintViolation constraintViolation : violations) { + sb.append(constraintViolation.getMessage()); + } + + dao.addUserAccount(useraccount); + + throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); + } + + + + return "Account for " + useraccount.getName() + " Added!"; + } + +} From d1b2f3af21ba9b8d9ab7fba3adb60c91b4f6b4cb Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Mon, 7 Jun 2021 15:52:34 +0530 Subject: [PATCH 105/114] moving spring service layer validation code --- .../spring-boot-servicelayer-validation}/.gitignore | 0 .../spring-boot-servicelayer-validation/README.md | 4 ++++ .../spring-boot-servicelayer-validation}/pom.xml | 0 .../SpringServiceLayerValidationApp.java | 0 .../controller/UserAccountController.java | 0 .../spring/servicevalidation/dao/UserAccountDao.java | 0 .../spring/servicevalidation/domain/UserAccount.java | 0 .../spring/servicevalidation/domain/UserAddress.java | 0 .../service/UserAccountService.java | 0 spring-service-layer-validation/README.md | 12 ------------ 10 files changed, 4 insertions(+), 12 deletions(-) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/.gitignore (100%) create mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/README.md rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/pom.xml (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java (100%) rename {spring-service-layer-validation => spring-boot-modules/spring-boot-servicelayer-validation}/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java (100%) delete mode 100644 spring-service-layer-validation/README.md diff --git a/spring-service-layer-validation/.gitignore b/spring-boot-modules/spring-boot-servicelayer-validation/.gitignore similarity index 100% rename from spring-service-layer-validation/.gitignore rename to spring-boot-modules/spring-boot-servicelayer-validation/.gitignore diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/README.md b/spring-boot-modules/spring-boot-servicelayer-validation/README.md new file mode 100644 index 0000000000..7c39135db6 --- /dev/null +++ b/spring-boot-modules/spring-boot-servicelayer-validation/README.md @@ -0,0 +1,4 @@ +## Spring Service Layer Validation + +This module contains articles about validation in Service layer of Spring Boot project. + diff --git a/spring-service-layer-validation/pom.xml b/spring-boot-modules/spring-boot-servicelayer-validation/pom.xml similarity index 100% rename from spring-service-layer-validation/pom.xml rename to spring-boot-modules/spring-boot-servicelayer-validation/pom.xml diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java similarity index 100% rename from spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java rename to spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md deleted file mode 100644 index 674831d6a5..0000000000 --- a/spring-service-layer-validation/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Spring Boot MVC - -This module contains articles about validation in Service layer of Spring Boot project. - -### Relevant Articles: - -- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) -- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) -- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) -- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) -- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) -- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) From d5399a7677d9612418cdcdd7e95f0179f7afb4c2 Mon Sep 17 00:00:00 2001 From: raviavhad Date: Sat, 24 Jul 2021 13:45:21 +0530 Subject: [PATCH 106/114] Update UserAccountService.java Moving the call to addUserAccount method out of condition to check if violations exist. --- .../servicevalidation/service/UserAccountService.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java index 9a376fda6b..c438719d3a 100644 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java +++ b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -29,15 +29,10 @@ public class UserAccountService { StringBuilder sb = new StringBuilder(); for (ConstraintViolation constraintViolation : violations) { sb.append(constraintViolation.getMessage()); - } - - dao.addUserAccount(useraccount); - + } throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); - } - - - + } + dao.addUserAccount(useraccount); return "Account for " + useraccount.getName() + " Added!"; } From ed01815cafeab2eaec9f4f11c721b5d37c24d9ab Mon Sep 17 00:00:00 2001 From: raviavhad Date: Sat, 24 Jul 2021 14:15:50 +0530 Subject: [PATCH 107/114] Update UserAccountService.java Reverting changes --- .../service/UserAccountService.java | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java index c438719d3a..417e9a32b7 100644 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java +++ b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -15,25 +15,28 @@ import com.baeldung.spring.servicevalidation.domain.UserAccount; @Service public class UserAccountService { - @Autowired - private Validator validator; - - @Autowired - private UserAccountDao dao; - - public String addUserAccount(UserAccount useraccount) { - - Set> violations = validator.validate(useraccount); + @Autowired + private Validator validator; - if (!violations.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (ConstraintViolation constraintViolation : violations) { - sb.append(constraintViolation.getMessage()); - } - throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); - } - dao.addUserAccount(useraccount); - return "Account for " + useraccount.getName() + " Added!"; - } + @Autowired + private UserAccountDao dao; + + public String addUserAccount(UserAccount useraccount) { + + Set> violations = validator.validate(useraccount); + + if (!violations.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (ConstraintViolation constraintViolation : violations) { + sb.append(constraintViolation.getMessage()); + } + + dao.addUserAccount(useraccount); + + throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); + } + + return "Account for " + useraccount.getName() + " Added!"; + } } From a9f9b29ef5d2bacbdf43e10064bbea29974dd643 Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Wed, 26 May 2021 23:39:55 +0530 Subject: [PATCH 108/114] Adding code for BAEL-4957 - Spring validation in the service layer --- spring-service-layer-validation/.gitignore | 63 +++++++++++++++ spring-service-layer-validation/README.md | 12 +++ spring-service-layer-validation/pom.xml | 46 +++++++++++ .../SpringServiceLayerValidationApp.java | 13 ++++ .../controller/UserAccountController.java | 22 ++++++ .../servicevalidation/dao/UserAccountDao.java | 32 ++++++++ .../servicevalidation/domain/UserAccount.java | 77 +++++++++++++++++++ .../servicevalidation/domain/UserAddress.java | 17 ++++ .../service/UserAccountService.java | 44 +++++++++++ 9 files changed, 326 insertions(+) create mode 100644 spring-service-layer-validation/.gitignore create mode 100644 spring-service-layer-validation/README.md create mode 100644 spring-service-layer-validation/pom.xml create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java create mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/.gitignore b/spring-service-layer-validation/.gitignore new file mode 100644 index 0000000000..8f5ee06047 --- /dev/null +++ b/spring-service-layer-validation/.gitignore @@ -0,0 +1,63 @@ +# Created by https://www.gitignore.io/api/eclipse + +### Eclipse ### + +.metadata +target/ +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Eclipse Patch ### +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# End of https://www.gitignore.io/api/eclipse \ No newline at end of file diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md new file mode 100644 index 0000000000..674831d6a5 --- /dev/null +++ b/spring-service-layer-validation/README.md @@ -0,0 +1,12 @@ +## Spring Boot MVC + +This module contains articles about validation in Service layer of Spring Boot project. + +### Relevant Articles: + +- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) +- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) +- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) +- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) +- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) +- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-service-layer-validation/pom.xml b/spring-service-layer-validation/pom.xml new file mode 100644 index 0000000000..31ec757699 --- /dev/null +++ b/spring-service-layer-validation/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + com.baeldung.spring-service-layer-validation + spring-service-layer-validation + 0.0.1-SNAPSHOT + + + UTF-8 + 12 + 12 + + + + org.springframework.boot + spring-boot-starter-parent + 2.4.5 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.hibernate.validator + hibernate-validator + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java new file mode 100644 index 0000000000..ea80a5da33 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.servicevalidation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringServiceLayerValidationApp { + + public static void main(String[] args) { + SpringApplication.run(SpringServiceLayerValidationApp.class, args); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java new file mode 100644 index 0000000000..b558ed89c2 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.servicevalidation.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; +import com.baeldung.spring.servicevalidation.service.UserAccountService; + +@RestController +public class UserAccountController { + + @Autowired + private UserAccountService service; + + @PostMapping("/addUserAccount") + public Object addUserAccount(@RequestBody UserAccount userAccount) { + return service.addUserAccount(userAccount); + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java new file mode 100644 index 0000000000..d170ceef58 --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.servicevalidation.dao; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountDao { + + private Map DB = new HashMap(); + + public String addUserAccount(UserAccount useraccount) { + DB.put(useraccount.getName(), useraccount); + return "success"; + } + + public Collection getAllUserAccounts() { + + Collection list = DB.values(); + if(list.isEmpty()) { + list.addAll(DB.values()); + } + return list; + + } + + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java new file mode 100644 index 0000000000..5b0e795a8a --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java @@ -0,0 +1,77 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class UserAccount { + + @NotNull(message = "Password must be between 4 to 15 characters") + @Size(min = 4, max = 15) + private String password; + + @NotBlank(message = "Name must not be blank") + private String name; + + @Min(value = 18, message = "Age should not be less than 18") + private int age; + + @NotBlank(message = "Phone must not be blank") + private String phone; + + @Valid + @NotNull(message = "UserAddress must not be blank") + private UserAddress useraddress; + + public UserAddress getUseraddress() { + return useraddress; + } + + public void setUseraddress(UserAddress useraddress) { + this.useraddress = useraddress; + } + + public UserAccount() { + + } + + public UserAccount(String email, String password, String name, int age) { + this.password = password; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java new file mode 100644 index 0000000000..85e7dfc05c --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.servicevalidation.domain; + +import javax.validation.constraints.NotBlank; +public class UserAddress { + + @NotBlank + private String countryCode; + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + +} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java new file mode 100644 index 0000000000..9a376fda6b --- /dev/null +++ b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.servicevalidation.service; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.spring.servicevalidation.dao.UserAccountDao; +import com.baeldung.spring.servicevalidation.domain.UserAccount; + +@Service +public class UserAccountService { + + @Autowired + private Validator validator; + + @Autowired + private UserAccountDao dao; + + public String addUserAccount(UserAccount useraccount) { + + Set> violations = validator.validate(useraccount); + + if (!violations.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (ConstraintViolation constraintViolation : violations) { + sb.append(constraintViolation.getMessage()); + } + + dao.addUserAccount(useraccount); + + throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); + } + + + + return "Account for " + useraccount.getName() + " Added!"; + } + +} From 5955e7bb411482c7f51eb75e74e1fe834cc89da2 Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Mon, 7 Jun 2021 15:52:34 +0530 Subject: [PATCH 109/114] moving spring service layer validation code --- spring-service-layer-validation/.gitignore | 63 --------------- spring-service-layer-validation/README.md | 12 --- spring-service-layer-validation/pom.xml | 46 ----------- .../SpringServiceLayerValidationApp.java | 13 ---- .../controller/UserAccountController.java | 22 ------ .../servicevalidation/dao/UserAccountDao.java | 32 -------- .../servicevalidation/domain/UserAccount.java | 77 ------------------- .../servicevalidation/domain/UserAddress.java | 17 ---- .../service/UserAccountService.java | 44 ----------- 9 files changed, 326 deletions(-) delete mode 100644 spring-service-layer-validation/.gitignore delete mode 100644 spring-service-layer-validation/README.md delete mode 100644 spring-service-layer-validation/pom.xml delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java delete mode 100644 spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-service-layer-validation/.gitignore b/spring-service-layer-validation/.gitignore deleted file mode 100644 index 8f5ee06047..0000000000 --- a/spring-service-layer-validation/.gitignore +++ /dev/null @@ -1,63 +0,0 @@ -# Created by https://www.gitignore.io/api/eclipse - -### Eclipse ### - -.metadata -target/ -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -### Eclipse Patch ### -# Eclipse Core -.project - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# End of https://www.gitignore.io/api/eclipse \ No newline at end of file diff --git a/spring-service-layer-validation/README.md b/spring-service-layer-validation/README.md deleted file mode 100644 index 674831d6a5..0000000000 --- a/spring-service-layer-validation/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Spring Boot MVC - -This module contains articles about validation in Service layer of Spring Boot project. - -### Relevant Articles: - -- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error) -- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) -- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) -- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) -- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) -- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-service-layer-validation/pom.xml b/spring-service-layer-validation/pom.xml deleted file mode 100644 index 31ec757699..0000000000 --- a/spring-service-layer-validation/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - 4.0.0 - - com.baeldung.spring-service-layer-validation - spring-service-layer-validation - 0.0.1-SNAPSHOT - - - UTF-8 - 12 - 12 - - - - org.springframework.boot - spring-boot-starter-parent - 2.4.5 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.hibernate.validator - hibernate-validator - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java deleted file mode 100644 index ea80a5da33..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.spring.servicevalidation; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringServiceLayerValidationApp { - - public static void main(String[] args) { - SpringApplication.run(SpringServiceLayerValidationApp.class, args); - } - -} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java deleted file mode 100644 index b558ed89c2..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.spring.servicevalidation.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import com.baeldung.spring.servicevalidation.domain.UserAccount; -import com.baeldung.spring.servicevalidation.service.UserAccountService; - -@RestController -public class UserAccountController { - - @Autowired - private UserAccountService service; - - @PostMapping("/addUserAccount") - public Object addUserAccount(@RequestBody UserAccount userAccount) { - return service.addUserAccount(userAccount); - } - -} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java deleted file mode 100644 index d170ceef58..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.spring.servicevalidation.dao; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.stereotype.Service; - -import com.baeldung.spring.servicevalidation.domain.UserAccount; - -@Service -public class UserAccountDao { - - private Map DB = new HashMap(); - - public String addUserAccount(UserAccount useraccount) { - DB.put(useraccount.getName(), useraccount); - return "success"; - } - - public Collection getAllUserAccounts() { - - Collection list = DB.values(); - if(list.isEmpty()) { - list.addAll(DB.values()); - } - return list; - - } - - -} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java deleted file mode 100644 index 5b0e795a8a..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.baeldung.spring.servicevalidation.domain; - -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -public class UserAccount { - - @NotNull(message = "Password must be between 4 to 15 characters") - @Size(min = 4, max = 15) - private String password; - - @NotBlank(message = "Name must not be blank") - private String name; - - @Min(value = 18, message = "Age should not be less than 18") - private int age; - - @NotBlank(message = "Phone must not be blank") - private String phone; - - @Valid - @NotNull(message = "UserAddress must not be blank") - private UserAddress useraddress; - - public UserAddress getUseraddress() { - return useraddress; - } - - public void setUseraddress(UserAddress useraddress) { - this.useraddress = useraddress; - } - - public UserAccount() { - - } - - public UserAccount(String email, String password, String name, int age) { - this.password = password; - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - -} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java deleted file mode 100644 index 85e7dfc05c..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.spring.servicevalidation.domain; - -import javax.validation.constraints.NotBlank; -public class UserAddress { - - @NotBlank - private String countryCode; - - public String getCountryCode() { - return countryCode; - } - - public void setCountryCode(String countryCode) { - this.countryCode = countryCode; - } - -} diff --git a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java deleted file mode 100644 index 9a376fda6b..0000000000 --- a/spring-service-layer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.spring.servicevalidation.service; - -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.Validator; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.baeldung.spring.servicevalidation.dao.UserAccountDao; -import com.baeldung.spring.servicevalidation.domain.UserAccount; - -@Service -public class UserAccountService { - - @Autowired - private Validator validator; - - @Autowired - private UserAccountDao dao; - - public String addUserAccount(UserAccount useraccount) { - - Set> violations = validator.validate(useraccount); - - if (!violations.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (ConstraintViolation constraintViolation : violations) { - sb.append(constraintViolation.getMessage()); - } - - dao.addUserAccount(useraccount); - - throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); - } - - - - return "Account for " + useraccount.getName() + " Added!"; - } - -} From d63ff1db3291a6d2843e3e5dcfed8909329d8e6f Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Sat, 24 Jul 2021 14:21:40 +0530 Subject: [PATCH 110/114] syncing with master --- .../.gitignore | 63 --------------- .../README.md | 4 - .../pom.xml | 46 ----------- .../SpringServiceLayerValidationApp.java | 13 ---- .../controller/UserAccountController.java | 22 ------ .../servicevalidation/dao/UserAccountDao.java | 32 -------- .../servicevalidation/domain/UserAccount.java | 77 ------------------- .../servicevalidation/domain/UserAddress.java | 17 ---- .../service/UserAccountService.java | 42 ---------- 9 files changed, 316 deletions(-) delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/.gitignore delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/README.md delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/pom.xml delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java delete mode 100644 spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/.gitignore b/spring-boot-modules/spring-boot-servicelayer-validation/.gitignore deleted file mode 100644 index 8f5ee06047..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/.gitignore +++ /dev/null @@ -1,63 +0,0 @@ -# Created by https://www.gitignore.io/api/eclipse - -### Eclipse ### - -.metadata -target/ -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -### Eclipse Patch ### -# Eclipse Core -.project - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# End of https://www.gitignore.io/api/eclipse \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/README.md b/spring-boot-modules/spring-boot-servicelayer-validation/README.md deleted file mode 100644 index 7c39135db6..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Spring Service Layer Validation - -This module contains articles about validation in Service layer of Spring Boot project. - diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/pom.xml b/spring-boot-modules/spring-boot-servicelayer-validation/pom.xml deleted file mode 100644 index 31ec757699..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - 4.0.0 - - com.baeldung.spring-service-layer-validation - spring-service-layer-validation - 0.0.1-SNAPSHOT - - - UTF-8 - 12 - 12 - - - - org.springframework.boot - spring-boot-starter-parent - 2.4.5 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.hibernate.validator - hibernate-validator - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java deleted file mode 100644 index ea80a5da33..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/SpringServiceLayerValidationApp.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.spring.servicevalidation; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringServiceLayerValidationApp { - - public static void main(String[] args) { - SpringApplication.run(SpringServiceLayerValidationApp.class, args); - } - -} diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java deleted file mode 100644 index b558ed89c2..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/controller/UserAccountController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.spring.servicevalidation.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import com.baeldung.spring.servicevalidation.domain.UserAccount; -import com.baeldung.spring.servicevalidation.service.UserAccountService; - -@RestController -public class UserAccountController { - - @Autowired - private UserAccountService service; - - @PostMapping("/addUserAccount") - public Object addUserAccount(@RequestBody UserAccount userAccount) { - return service.addUserAccount(userAccount); - } - -} diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java deleted file mode 100644 index d170ceef58..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/dao/UserAccountDao.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.spring.servicevalidation.dao; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.stereotype.Service; - -import com.baeldung.spring.servicevalidation.domain.UserAccount; - -@Service -public class UserAccountDao { - - private Map DB = new HashMap(); - - public String addUserAccount(UserAccount useraccount) { - DB.put(useraccount.getName(), useraccount); - return "success"; - } - - public Collection getAllUserAccounts() { - - Collection list = DB.values(); - if(list.isEmpty()) { - list.addAll(DB.values()); - } - return list; - - } - - -} diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java deleted file mode 100644 index 5b0e795a8a..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAccount.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.baeldung.spring.servicevalidation.domain; - -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -public class UserAccount { - - @NotNull(message = "Password must be between 4 to 15 characters") - @Size(min = 4, max = 15) - private String password; - - @NotBlank(message = "Name must not be blank") - private String name; - - @Min(value = 18, message = "Age should not be less than 18") - private int age; - - @NotBlank(message = "Phone must not be blank") - private String phone; - - @Valid - @NotNull(message = "UserAddress must not be blank") - private UserAddress useraddress; - - public UserAddress getUseraddress() { - return useraddress; - } - - public void setUseraddress(UserAddress useraddress) { - this.useraddress = useraddress; - } - - public UserAccount() { - - } - - public UserAccount(String email, String password, String name, int age) { - this.password = password; - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - -} diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java deleted file mode 100644 index 85e7dfc05c..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/domain/UserAddress.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.spring.servicevalidation.domain; - -import javax.validation.constraints.NotBlank; -public class UserAddress { - - @NotBlank - private String countryCode; - - public String getCountryCode() { - return countryCode; - } - - public void setCountryCode(String countryCode) { - this.countryCode = countryCode; - } - -} diff --git a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java deleted file mode 100644 index 417e9a32b7..0000000000 --- a/spring-boot-modules/spring-boot-servicelayer-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.spring.servicevalidation.service; - -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.Validator; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.baeldung.spring.servicevalidation.dao.UserAccountDao; -import com.baeldung.spring.servicevalidation.domain.UserAccount; - -@Service -public class UserAccountService { - - @Autowired - private Validator validator; - - @Autowired - private UserAccountDao dao; - - public String addUserAccount(UserAccount useraccount) { - - Set> violations = validator.validate(useraccount); - - if (!violations.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (ConstraintViolation constraintViolation : violations) { - sb.append(constraintViolation.getMessage()); - } - - dao.addUserAccount(useraccount); - - throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); - } - - return "Account for " + useraccount.getName() + " Added!"; - } - -} From 6b3e8de50fdce89a4525b515c9c8eeb48effd692 Mon Sep 17 00:00:00 2001 From: Ravi Avhad Date: Sat, 24 Jul 2021 14:25:40 +0530 Subject: [PATCH 111/114] Moving method addUserAccount out of conditional block which checks for contraint violations --- .../spring/servicevalidation/service/UserAccountService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-boot-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java b/spring-boot-modules/spring-boot-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java index 417e9a32b7..9d79e4e226 100644 --- a/spring-boot-modules/spring-boot-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java +++ b/spring-boot-modules/spring-boot-validation/src/main/java/com/baeldung/spring/servicevalidation/service/UserAccountService.java @@ -31,11 +31,10 @@ public class UserAccountService { sb.append(constraintViolation.getMessage()); } - dao.addUserAccount(useraccount); - throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); } + dao.addUserAccount(useraccount); return "Account for " + useraccount.getName() + " Added!"; } From ec02aed456154ea2b3ab9b155de68d00a50e0f36 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Sun, 25 Jul 2021 08:34:25 +0200 Subject: [PATCH 112/114] JAVA-6253: Review the time of the build (#11067) * JAVA-6253: Move image-processing to the heavy profile * JAVA-6253: Do not start blade app automatically by a plugin Co-authored-by: Krzysztof Woyke --- blade/pom.xml | 32 -------------------------------- pom.xml | 6 ++++-- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/blade/pom.xml b/blade/pom.xml index b763f69c85..f4bc6d73be 100644 --- a/blade/pom.xml +++ b/blade/pom.xml @@ -84,38 +84,6 @@ - - com.bazaarvoice.maven.plugins - process-exec-maven-plugin - ${process-exec-maven-plugin.version} - - - - blade-process - pre-integration-test - - start - - - Blade - false - - java - -jar - blade.jar - - - - - - stop-all - post-integration-test - - stop-all - - - - maven-assembly-plugin ${assembly.plugin.version} diff --git a/pom.xml b/pom.xml index acdb0a95fd..abdb851734 100644 --- a/pom.xml +++ b/pom.xml @@ -428,7 +428,6 @@ httpclient-simple hystrix - image-processing immutables jackson-modules @@ -751,6 +750,8 @@ parent-spring-5 parent-java + image-processing + jenkins/plugins jhipster jws @@ -895,7 +896,6 @@ httpclient-simple hystrix - image-processing immutables jackson-modules @@ -1200,6 +1200,8 @@ parent-spring-5 parent-java + image-processing + jenkins/plugins jhipster jws From dd50f5e80bdb0862bf88f528356f3c50c8db71f4 Mon Sep 17 00:00:00 2001 From: Usman Mohyuddin Date: Sun, 25 Jul 2021 22:02:16 +0500 Subject: [PATCH 113/114] Create GreetingsController.java (#11057) * Create GreetingsController.java add controller to test the content type being set properly or not * add unit tests for greetings controller * update to avoid PMD violation * correct the file type * Update GreetingsControllerUnitTest.java fix some imports & correct the names * Update GreetingsControllerUnitTest.java update the unit case to avoid internal server error for junit --- .../controller/GreetingsController.java | 49 ++++++++++++++++ .../GreetingsControllerUnitTest.java | 58 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/GreetingsController.java create mode 100644 spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/GreetingsControllerUnitTest.java diff --git a/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/GreetingsController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/GreetingsController.java new file mode 100644 index 0000000000..fbf78b8a0e --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/GreetingsController.java @@ -0,0 +1,49 @@ +package com.baeldung.controller.controller; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class GreetingsController { + + @RequestMapping( + value = "/greetings-with-response-body", + method = RequestMethod.GET, + produces="application/json" + ) + @ResponseBody + public String getGreetingWhileReturnTypeIsString() { + return "{\"test\": \"Hello using @ResponseBody\"}"; + } + + @RequestMapping( + value = "/greetings-with-response-entity", + method = RequestMethod.GET, + produces = "application/json" + ) + public ResponseEntity getGreetingWithResponseEntity() { + final HttpHeaders httpHeaders= new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + return new ResponseEntity("{\"test\": \"Hello with ResponseEntity\"}", httpHeaders, HttpStatus.OK); + } + @RequestMapping( + value = "/greetings-with-map-return-type", + method = RequestMethod.GET, + produces = "application/json" + ) + @ResponseBody + public Map getGreetingWhileReturnTypeIsMap() { + HashMap map = new HashMap(); + map.put("test", "Hello from map"); + return map; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/GreetingsControllerUnitTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/GreetingsControllerUnitTest.java new file mode 100644 index 0000000000..ee9a8da8d4 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/GreetingsControllerUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.baeldung.controller.controller.GreetingsController; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.AnnotationConfigWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { GreetingsController.class }, loader = AnnotationConfigWebContextLoader.class) +public class GreetingsControllerUnitTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenReturnTypeIsString_whenJacksonOnClasspath_thenDefaultContentTypeIsJSON() throws Exception { + + // Given + String expectedMimeType = "application/json"; + + // Then + String actualMimeType = this.mockMvc.perform(MockMvcRequestBuilders.get("/greetings-with-response-body", 1)).andReturn().getResponse().getContentType(); + + Assert.assertEquals(expectedMimeType, actualMimeType); + + } + + @Test + public void givenReturnTypeIsResponseEntity_thenDefaultContentTypeIsJSON() throws Exception { + + // Given + String expectedMimeType = "application/json"; + + // Then + String actualMimeType = this.mockMvc.perform(MockMvcRequestBuilders.get("/greetings-with-response-entity", 1)).andReturn().getResponse().getContentType(); + + Assert.assertEquals(expectedMimeType, actualMimeType); + } +} \ No newline at end of file From 54f85ac6cd1cd79ec778478eaf92c3742e099f53 Mon Sep 17 00:00:00 2001 From: mdabrowski-eu <57441874+mdabrowski-eu@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:58:35 +0200 Subject: [PATCH 114/114] BAEL-4814 Bitmasking in Java with Bitwise Operators (#11069) --- .../oroperators/BitmaskingUnitTest.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/oroperators/BitmaskingUnitTest.java diff --git a/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/oroperators/BitmaskingUnitTest.java b/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/oroperators/BitmaskingUnitTest.java new file mode 100644 index 0000000000..9af59d7c1c --- /dev/null +++ b/core-java-modules/core-java-lang-operators-2/src/test/java/com/baeldung/oroperators/BitmaskingUnitTest.java @@ -0,0 +1,120 @@ +package com.baeldung.oroperators; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class BitmaskingUnitTest { + + @Test + public void givenIntegerShouldPrintBinaryRepresentation() { + // given + int intRepresentation = 1094795523; + + // expected + String stringRepresentation = getStringRepresentation(intRepresentation); + assertEquals(stringRepresentation, "01000001010000010100000100000011"); + } + + private String getStringRepresentation(int intRepresentation) { + String binaryString = Integer.toBinaryString(intRepresentation); + return padWithZeros(binaryString); + } + + private String padWithZeros(String binaryString) { + return String.format("%" + 32 + "s", binaryString).replace(' ', '0'); + } + + @Test + public void givenBinaryRepresentationShouldReturnNumber() { + // given + String stringRepresentation = "01000001010000010100000100000011"; + + // expected + int intRepresentation = Integer.parseUnsignedInt(stringRepresentation, 2); + assertEquals(intRepresentation, 1094795523); + } + + @Test + public void givenBinaryRepresentationShouldReturnCharacter() { + // given + String stringRepresentation = "010000010100000101000001"; + + // expected + assertEquals(binaryToText(stringRepresentation), "AAA"); + } + + @Test + public void givenIntAndPositionNumberShouldReturnBitValue() { + // given + String stringRepresentation = "010000010100000101000001000000011"; + int intRepresentation = Integer.parseUnsignedInt(stringRepresentation, 2); + + // when + boolean value1 = extractValueAtPosition(intRepresentation, 1); + boolean value2 = extractValueAtPosition(intRepresentation, 2); + boolean value3 = extractValueAtPosition(intRepresentation, 3); + + // then + assertTrue(value1); + assertTrue(value2); + assertFalse(value3); + + } + + @Test + public void givenIntegerShouldExtractLastThreeBytes() { + // given + int intRepresentation = 1094795523; + + // when + int lastThreeBites = intRepresentation >> 8; + + // expected + String stringRepresentation = getStringRepresentation(lastThreeBites); + assertEquals(stringRepresentation, "00000000010000010100000101000001"); + assertEquals(binaryToText(stringRepresentation), "AAA"); + } + + @Test + public void givenIntegerShouldApplyMask() { + // given + int intRepresentation = Integer.parseUnsignedInt("00000000010000010100000101000001", 2); + int mask = Integer.parseUnsignedInt("00000000000000000000000000000011", 2); + int mask2 = Integer.parseUnsignedInt("00000000000000000000000000000001", 2); + + // when + int masked = intRepresentation & mask; + int masked2 = intRepresentation & mask2; + + // expected + assertEquals(getStringRepresentation(masked), "00000000000000000000000000000001"); + assertEquals(getStringRepresentation(masked2), "00000000000000000000000000000001"); + assertNotEquals(masked, mask); + assertEquals(masked2, mask2); + assertFalse((intRepresentation & mask) == mask); + } + + private boolean extractValueAtPosition(int intRepresentation, int position) { + String mask = getStringRepresentation(1 << (position - 1)); + System.out.println(getStringRepresentation(intRepresentation)); + System.out.println(mask); + System.out.println("-------------------------------- &"); + System.out.println(getStringRepresentation((intRepresentation) & (1 << (position - 1)))); + System.out.println(); + return ((intRepresentation) & (1 << (position - 1))) != 0; + } + + private static String binaryToText(String stringRepresentation) { + return Arrays.stream(stringRepresentation.split("(?<=\\G.{8})")) + .filter(eightBits -> !eightBits.equals("00000000")) + .map(eightBits -> (char)Integer.parseInt(eightBits, 2)) + .collect( + StringBuilder::new, + StringBuilder::append, + StringBuilder::append + ).toString(); + } +}